= Traversing the !MeshObjectGraph = == Traversal to neighbor !MeshObjects == Given a start MeshObject: {{{ MeshObject start = ...; }}} the MeshObject's neighbor [wiki:MeshObject MeshObjects] can be found as follows: {{{ MeshObjectSet neighbors = start.traverseToNeighborMeshObjects(); }}} The returned MeshObjectSet contains zero or more [wiki:MeshObject MeshObjects] that can be iterated over or accessed directly. It contains all neighbors of the start MeshObject, regardless of whether the [wiki:Relationship Relationships] are blessed or not. == Traversal to neighbor !MeshObjects related with a certain !RelationshipType == To determine only those neighbor [wiki:MeshObject MeshObjects] that are related to the start MeshObject with a [wiki:Relationship] blessed with RelationshipType `org.infogrid.model.Tagging/Tag_Tags_MeshObject`: {{{ MeshObject start = ...; MeshObjectSet someNeighbors = start.traverse( TaggingSubjectArea.TAG_TAGS_MESHOBJECT.getSource() ); }}} Note that this RelationshipType is directed. The example [wiki:Traversal] traverses from the "Tag" MeshObject to the "tagged" MeshObject. To traverse from the "tagged" MeshObject to the "Tag" MeshObject: {{{ MeshObjectSet otherNeighbors = start.traverse( TaggingSubjectArea.TAG_TAGS_MESHOBJECT.getDestination() ); }}} == Complex Traversals == Sometimes it is convenient to define a complex graph [wiki:Traversal] once, and reuse it several times. For this purpose, InfoGrid provides the concept of a TraversalSpecification. For example, assume the following [wiki:Model] for representing ancestry in a hypothetical `Ancestry` SubjectArea: * EntityType `Person`, with subtypes `MalePerson` and `FemalePerson`. * RelationshipType `Person_HasChild_Person`. Assuming a given `Person` MeshObject, one could define the following TraversalSpecification to find that `Person`'s great-grandfathers: {{{ TraversalSpecification toGreatGrandfathers = SequentialCompoundTraversalSpecification.create( new TraversalSpecification [] { AncestrySubjectArea.PERSON_HASCHILD_PERSON.getDestination(), // from person to their parents AncestrySubjectArea.PERSON_HASCHILD_PERSON.getDestination(), // from parents to grandparents SelectiveTraversalSpecification.create( AncestrySubjectArea.PERSON_HASCHILD_PERSON.getDestination(), // from grandparents to great-grandparents ByTypeMeshObjectSelector.create( AncestrySubjectArea.MALEPERSON, true )) // but only males } ); }}} This TraversalSpecification is of type `SequentialCompoundTraversalSpecification`, which means is consists of a sequence of [wiki:TraversalSpecification TraversalSpecifications] to be traversed in sequence. The first two are the same RoleType that relates a child to their parents. Traversing those two reaches the grandparents. To reach the great-grandparents, the same RoleType needs to be traversed, but we only want those found [wiki:MeshObject MeshObjects] that are of type `MalePerson`. To accomplish this, the RoleType is wrapped by a `SelectiveTraversalSpecification`, which subsets the result of a [wiki:Traversal]. The `ByTypeMeshObjectSelector` is used to select only males. The `true` flag indicates that if, in the future, subtypes of `MalePerson` were to be defined, they would also be selected. In spite of its complexity, this TraversalSpecification can be used in the same manner as a simple RoleType: {{{ MeshObject me = ...; // start object MeshObjectSet greatGrandFathers = me.traverse( toGreatGrandfathers ); }}} The TraversalSpecification abstraction can make applications substantially more maintainable if an application's [wiki:Model] keeps changing. See also: * KeywordTraversalTranslator * XpathTraversalTranslator