PageRenderTime 36ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/plexus-0.13.1/src/java/com/phoenixst/plexus/TraverserPredicateFactory.java

#
Java | 457 lines | 269 code | 75 blank | 113 comment | 36 complexity | c3e92d1b596169028ccfcf46ee03a072 MD5 | raw file
Possible License(s): CPL-1.0
  1. /*
  2. * $Id: TraverserPredicateFactory.java,v 1.12 2005/10/03 15:24:00 rconner Exp $
  3. *
  4. * Copyright (C) 1994-2005 by Phoenix Software Technologists,
  5. * Inc. and others. All rights reserved.
  6. *
  7. * THIS PROGRAM AND DOCUMENTATION IS PROVIDED UNDER THE TERMS OF THE
  8. * COMMON PUBLIC LICENSE ("AGREEMENT") WHICH ACCOMPANIES IT. ANY
  9. * USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES
  10. * RECIPIENT'S ACCEPTANCE OF THE AGREEMENT.
  11. *
  12. * The license text can also be found at
  13. * http://opensource.org/licenses/cpl.php
  14. */
  15. package com.phoenixst.plexus;
  16. import java.io.*;
  17. import org.apache.commons.collections.Predicate;
  18. import com.phoenixst.collections.*;
  19. /**
  20. * A factory for creating {@link TraverserPredicate
  21. * TraverserPredicates}.
  22. *
  23. * @version $Revision: 1.12 $
  24. * @author Ray A. Conner
  25. *
  26. * @since 1.0
  27. */
  28. public class TraverserPredicateFactory
  29. {
  30. ////////////////////////////////////////
  31. // Private constructor
  32. ////////////////////////////////////////
  33. private TraverserPredicateFactory()
  34. {
  35. super();
  36. }
  37. ////////////////////////////////////////
  38. // Static factory methods
  39. ////////////////////////////////////////
  40. /**
  41. * Creates a new <code>TraverserPredicate</code> which tests for
  42. * <code>Graph.Edges</code> which look just like the specified
  43. * <code>edge</code>, ignoring one endpoint.
  44. *
  45. * <P>If <code>fromTail</code> is <code>true</code>, then the
  46. * returned <code>Predicate</code> tests for traversals over
  47. * <code>Graph.Edges</code> that contain the same user object, to
  48. * the head of the specified <code>edge</code>, with the same
  49. * directedness. In other words, test as if traversing from the
  50. * tail looking for a similar <code>Graph.Edge</code>, although
  51. * the tail itself is not checked.
  52. *
  53. * <P>If <code>fromTail</code> is <code>false</code>, then the
  54. * returned <code>Predicate</code> tests for traversals over
  55. * <code>Graph.Edges</code> that contain the same user object, to
  56. * the tail of the specified <code>edge</code>, with the same
  57. * directedness. In other words, test as if traversing from the
  58. * head looking for a similar <code>Graph.Edge</code>, although
  59. * the head itself is not checked.
  60. */
  61. public static final TraverserPredicate create( Graph.Edge edge,
  62. boolean fromTail )
  63. {
  64. Object node;
  65. int directionFlags;
  66. if( fromTail ) {
  67. directionFlags = edge.isDirected()
  68. ? GraphUtils.DIRECTED_OUT_MASK
  69. : GraphUtils.UNDIRECTED_MASK;
  70. node = edge.getHead();
  71. } else {
  72. directionFlags = edge.isDirected()
  73. ? GraphUtils.DIRECTED_IN_MASK
  74. : GraphUtils.UNDIRECTED_MASK;
  75. node = edge.getTail();
  76. }
  77. return new EqualsUserNodePredicate( edge.getUserObject(),
  78. node,
  79. directionFlags );
  80. }
  81. /**
  82. * Creates a new <code>TraverserPredicate</code> which tests for
  83. * traversals to the specified <code>node</code>, with a
  84. * direction specified relative to the endpoint
  85. * <strong>from</strong> which the <code>Graph.Edge</code> is
  86. * being traversed.
  87. */
  88. public static final TraverserPredicate createEqualsNode( Object node,
  89. int directionFlags )
  90. {
  91. return new EqualsNodePredicate( node,
  92. directionFlags );
  93. }
  94. /**
  95. * Creates a new <code>TraverserPredicate</code> which tests for
  96. * traversals over <code>Graph.Edges</code> that contain the
  97. * specified user object, with a direction specified relative to
  98. * the endpoint <strong>from</strong> which the
  99. * <code>Graph.Edge</code> is being traversed.
  100. */
  101. public static final TraverserPredicate createEqualsUser( Object userObject,
  102. int directionFlags )
  103. {
  104. return new EqualsUserPredicate( userObject,
  105. directionFlags );
  106. }
  107. /**
  108. * Creates a new <code>TraverserPredicate</code> which tests for
  109. * traversals over <code>Graph.Edges</code> that contain the
  110. * specified user object, to the specified <code>node</code>,
  111. * with a direction specified relative to the endpoint
  112. * <strong>from</strong> which the <code>Graph.Edge</code> is
  113. * being traversed.
  114. */
  115. public static final TraverserPredicate createEquals( Object userObject,
  116. Object node,
  117. int directionFlags )
  118. {
  119. return new EqualsUserNodePredicate( userObject,
  120. node,
  121. directionFlags );
  122. }
  123. /**
  124. * Creates a new <code>TraverserPredicate</code> which tests for
  125. * traversals over <code>Graph.Edges</code> whose contained user
  126. * object satisfies <code>userObjectPredicate</code>, to a node
  127. * which satisfies <code>nodePredicate</code>, with a direction
  128. * specified relative to the endpoint <strong>from</strong> which
  129. * the <code>Graph.Edge</code> is being traversed.
  130. */
  131. public static final TraverserPredicate createPredicated( Predicate userObjectPredicate,
  132. Predicate nodePredicate,
  133. int directionFlags )
  134. {
  135. return new PredicatedUserNodePredicate( userObjectPredicate,
  136. nodePredicate,
  137. directionFlags );
  138. }
  139. ////////////////////////////////////////
  140. // Helper method
  141. ////////////////////////////////////////
  142. static Object escapePredicate( Object object )
  143. {
  144. return (object instanceof Predicate)
  145. ? new EqualPredicate( object )
  146. : object;
  147. }
  148. ////////////////////////////////////////
  149. // Private classes
  150. ////////////////////////////////////////
  151. private static abstract class AbstractTraverserPredicate
  152. implements TraverserPredicate,
  153. Serializable
  154. {
  155. private static final long serialVersionUID = 1L;
  156. /**
  157. * @serial
  158. */
  159. private final int directionFlags;
  160. /**
  161. * Package-private constructor, to be invoked by subclasses.
  162. */
  163. AbstractTraverserPredicate( int directionFlags )
  164. {
  165. super();
  166. this.directionFlags = directionFlags & GraphUtils.ANY_DIRECTION_MASK;
  167. if( this.directionFlags == 0 ) {
  168. throw new IllegalArgumentException( "Direction flags are invalid: " + directionFlags );
  169. }
  170. }
  171. private void readObject( ObjectInputStream in )
  172. throws ClassNotFoundException,
  173. IOException
  174. {
  175. in.defaultReadObject();
  176. if( (directionFlags & GraphUtils.ANY_DIRECTION_MASK) == 0 ) {
  177. throw new InvalidObjectException( "No direction flags set: " + directionFlags );
  178. }
  179. if( (directionFlags & GraphUtils.ANY_DIRECTION_MASK) != directionFlags ) {
  180. throw new InvalidObjectException( "Direction flags not valid: " + directionFlags );
  181. }
  182. }
  183. public Object getNodeSpecification()
  184. {
  185. return TruePredicate.INSTANCE;
  186. }
  187. public Object getUserObjectSpecification()
  188. {
  189. return TruePredicate.INSTANCE;
  190. }
  191. public int getDirectionFlags()
  192. {
  193. return directionFlags;
  194. }
  195. abstract boolean evaluate( Object targetUserObject, Object targetNode );
  196. public boolean evaluate( Object object )
  197. {
  198. OrderedPair pair = (OrderedPair) object;
  199. Object baseNode = pair.getFirst();
  200. Graph.Edge edge = (Graph.Edge) pair.getSecond();
  201. // Test direction
  202. if( edge.isDirected() ) {
  203. if( !( (directionFlags & GraphUtils.DIRECTED_OUT_MASK) != 0
  204. && GraphUtils.equals( baseNode, edge.getTail() ) )
  205. && !( (directionFlags & GraphUtils.DIRECTED_IN_MASK) != 0
  206. && GraphUtils.equals( baseNode, edge.getHead() ) ) ) {
  207. return false;
  208. }
  209. } else {
  210. if( (directionFlags & GraphUtils.UNDIRECTED_MASK) == 0 ) {
  211. return false;
  212. }
  213. }
  214. // Test everything else
  215. return evaluate( edge.getUserObject(), edge.getOtherEndpoint( baseNode ) );
  216. }
  217. public boolean equals( Object object )
  218. {
  219. if( object == this ) {
  220. return true;
  221. }
  222. if( object == null ) {
  223. return false;
  224. }
  225. if( !getClass().equals( object.getClass() ) ) {
  226. return false;
  227. }
  228. TraverserPredicate pred = (TraverserPredicate) object;
  229. return getDirectionFlags() == pred.getDirectionFlags()
  230. && getUserObjectSpecification().equals( pred.getUserObjectSpecification() )
  231. && getNodeSpecification().equals( pred.getNodeSpecification() );
  232. }
  233. public int hashCode()
  234. {
  235. // 17 & 37 are arbitrary, but non-zero and prime
  236. int result = 17;
  237. result = 37 * result + getUserObjectSpecification().hashCode();
  238. result = 37 * result + getNodeSpecification().hashCode();
  239. result = 37 * result + getDirectionFlags();
  240. return result;
  241. }
  242. public String toString()
  243. {
  244. StringBuilder s = new StringBuilder( "TraverserPredicate( {" );
  245. s.append( GraphUtils.directionFlagsToString( getDirectionFlags() ) );
  246. s.append( "} [");
  247. s.append( getUserObjectSpecification() );
  248. s.append( "] -- [");
  249. s.append( getNodeSpecification() );
  250. s.append( "] )");
  251. return s.toString();
  252. }
  253. }
  254. private static final class EqualsNodePredicate extends AbstractTraverserPredicate
  255. {
  256. private static final long serialVersionUID = 1L;
  257. /**
  258. * @serial
  259. */
  260. private final Object node;
  261. EqualsNodePredicate( Object node,
  262. int directionFlags )
  263. {
  264. super( directionFlags );
  265. this.node = node;
  266. }
  267. public Object getNodeSpecification()
  268. {
  269. return escapePredicate( node );
  270. }
  271. boolean evaluate( Object targetUserObject, Object targetNode )
  272. {
  273. return GraphUtils.equals( node, targetNode );
  274. }
  275. }
  276. private static final class EqualsUserPredicate extends AbstractTraverserPredicate
  277. {
  278. private static final long serialVersionUID = 1L;
  279. /**
  280. * @serial
  281. */
  282. private final Object userObject;
  283. EqualsUserPredicate( Object userObject,
  284. int directionFlags )
  285. {
  286. super( directionFlags );
  287. this.userObject = userObject;
  288. }
  289. public Object getUserObjectSpecification()
  290. {
  291. return escapePredicate( userObject );
  292. }
  293. boolean evaluate( Object targetUserObject, Object targetNode )
  294. {
  295. return GraphUtils.equals( userObject, targetUserObject );
  296. }
  297. }
  298. private static final class EqualsUserNodePredicate extends AbstractTraverserPredicate
  299. {
  300. private static final long serialVersionUID = 1L;
  301. /**
  302. * @serial
  303. */
  304. private final Object userObject;
  305. /**
  306. * @serial
  307. */
  308. private final Object node;
  309. EqualsUserNodePredicate( Object userObject,
  310. Object node,
  311. int directionFlags )
  312. {
  313. super( directionFlags );
  314. this.userObject = userObject;
  315. this.node = node;
  316. }
  317. public Object getNodeSpecification()
  318. {
  319. return escapePredicate( node );
  320. }
  321. public Object getUserObjectSpecification()
  322. {
  323. return escapePredicate( userObject );
  324. }
  325. boolean evaluate( Object targetUserObject, Object targetNode )
  326. {
  327. return GraphUtils.equals( userObject, targetUserObject )
  328. && GraphUtils.equals( node, targetNode );
  329. }
  330. }
  331. private static final class PredicatedUserNodePredicate extends AbstractTraverserPredicate
  332. {
  333. private static final long serialVersionUID = 1L;
  334. /**
  335. * @serial
  336. */
  337. private final Predicate userObjectPredicate;
  338. /**
  339. * @serial
  340. */
  341. private final Predicate nodePredicate;
  342. PredicatedUserNodePredicate( Predicate userObjectPredicate,
  343. Predicate nodePredicate,
  344. int directionFlags )
  345. {
  346. super( directionFlags );
  347. this.userObjectPredicate = userObjectPredicate;
  348. this.nodePredicate = nodePredicate;
  349. if( userObjectPredicate == null ) {
  350. throw new IllegalArgumentException( "User object Predicate is null." );
  351. }
  352. if( nodePredicate == null ) {
  353. throw new IllegalArgumentException( "Node Predicate is null." );
  354. }
  355. }
  356. private void readObject( ObjectInputStream in )
  357. throws ClassNotFoundException,
  358. IOException
  359. {
  360. in.defaultReadObject();
  361. if( userObjectPredicate == null ) {
  362. throw new InvalidObjectException( "User object Predicate is null." );
  363. }
  364. if( nodePredicate == null ) {
  365. throw new InvalidObjectException( "Node Predicate is null." );
  366. }
  367. }
  368. public Object getUserObjectSpecification()
  369. {
  370. return userObjectPredicate;
  371. }
  372. public Object getNodeSpecification()
  373. {
  374. return nodePredicate;
  375. }
  376. boolean evaluate( Object targetUserObject, Object targetNode )
  377. {
  378. return userObjectPredicate.evaluate( targetUserObject )
  379. && nodePredicate.evaluate( targetNode );
  380. }
  381. }
  382. }