1 | /* |
2 | * $Id: StepPredicates.java 562 2010-11-11 00:28:13Z PSpeed $ |
3 | * |
4 | * The Filament BSD license. |
5 | * |
6 | * Copyright (c) 2009-2010, the original author or authors |
7 | * |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions |
10 | * are met: |
11 | * |
12 | * 1) Redistributions of source code must retain the above copyright notice, |
13 | * this list of conditions and the following disclaimer. |
14 | * 2) Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. |
17 | * 3) Neither the names "Filament", "fgraph.org", "filamentgraph.org", nor the |
18 | * names of its contributors may be used to endorse or promote products |
19 | * derived from this software without specific prior written permission. |
20 | * |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
25 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
31 | * POSSIBILITY OF SUCH DAMAGE. |
32 | */ |
33 | |
34 | package org.fgraph.steps; |
35 | |
36 | import java.io.Serializable; |
37 | import java.util.*; |
38 | |
39 | import com.google.common.base.Predicate; |
40 | |
41 | |
42 | /** |
43 | * Set of utility predicates for the fsteps package. |
44 | * |
45 | * <p>Unless otherwise specified, all methods return serializable |
46 | * predicates as long as they're given serializable parameters.</p> |
47 | * |
48 | * @version $Revision: 562 $ |
49 | * @author Paul Speed |
50 | */ |
51 | public class StepPredicates |
52 | { |
53 | /** |
54 | * Returns a filter that returns true for steps less than |
55 | * or equal to a certain depth. |
56 | */ |
57 | public static <T extends Step> Predicate<T> maxDepth( int depth ) |
58 | { |
59 | return new DepthPredicate<T>( depth, 1 ); |
60 | } |
61 | |
62 | /** |
63 | * Returns a filter that returns true for steps greater |
64 | * than or equal to a certain depth. |
65 | */ |
66 | public static <T extends Step> Predicate<T> minDepth( int depth ) |
67 | { |
68 | return new DepthPredicate<T>( depth, -1 ); |
69 | } |
70 | |
71 | /** |
72 | * Returns a filter that returns true for steps at the |
73 | * specified depth. |
74 | */ |
75 | public static <T extends Step> Predicate<T> depth( int depth ) |
76 | { |
77 | return new DepthPredicate<T>( depth, 0 ); |
78 | } |
79 | |
80 | /** |
81 | * Returns a filter that returns true for steps that are descending. |
82 | */ |
83 | public static <T> Predicate<DepthFirstStep<T>> descending() |
84 | { |
85 | return new DescentPredicate<T>(true); |
86 | } |
87 | |
88 | /** |
89 | * Returns a filter that returns true for steps that are ascending. |
90 | */ |
91 | public static <T> Predicate<DepthFirstStep<T>> ascending() |
92 | { |
93 | return new DescentPredicate<T>(false); |
94 | } |
95 | |
96 | private static class DepthPredicate<T extends Step> implements Predicate<T>, Serializable |
97 | { |
98 | static final long serialVersionUID = 1L; |
99 | |
100 | private int depth; |
101 | private int sign; |
102 | |
103 | public DepthPredicate( int depth, int sign ) |
104 | { |
105 | this.depth = depth; |
106 | this.sign = sign; |
107 | } |
108 | |
109 | public boolean apply( T step ) |
110 | { |
111 | long diff = (long)depth - (long)step.getDepth(); |
112 | if( sign == 0 ) |
113 | return diff == 0; |
114 | return (diff * sign) >= 0; |
115 | } |
116 | |
117 | public String toString() |
118 | { |
119 | String comp = ""; |
120 | switch( sign ) |
121 | { |
122 | case -1: |
123 | comp = ">="; |
124 | break; |
125 | case 1: |
126 | comp = "<="; |
127 | break; |
128 | case 0: |
129 | comp = "=="; |
130 | break; |
131 | /* |
132 | This can never happen since this class is |
133 | private and only ever called by internal values... |
134 | it's impossible to cover in unit tests. |
135 | default: |
136 | comp = "??"; |
137 | break;*/ |
138 | } |
139 | return "DepthPredicate[" + comp + " " + depth + "]"; |
140 | } |
141 | } |
142 | |
143 | private static class DescentPredicate<T> implements Predicate<DepthFirstStep<T>>, Serializable |
144 | { |
145 | static final long serialVersionUID = 1L; |
146 | |
147 | private boolean descending; |
148 | |
149 | public DescentPredicate( boolean descending ) |
150 | { |
151 | this.descending = descending; |
152 | } |
153 | |
154 | public boolean apply( DepthFirstStep<T> step ) |
155 | { |
156 | return step.isDescending() == descending; |
157 | } |
158 | |
159 | public String toString() |
160 | { |
161 | return descending ? "Descending[]" : "Ascending[]"; |
162 | } |
163 | } |
164 | } |