View Javadoc

1   /**
2    * Copyright (c) 2002-2011 "Neo Technology,"
3    * Network Engine for Objects in Lund AB [http://neotechnology.com]
4    *
5    * This file is part of Neo4j.
6    *
7    * Neo4j is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation, either version 3 of the License, or
10   * (at your option) any later version.
11   *
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.neo4j.server.rest.domain;
21  
22  import java.util.Arrays;
23  import java.util.Collection;
24  import java.util.Map;
25  
26  import org.neo4j.graphdb.DynamicRelationshipType;
27  import org.neo4j.graphdb.RelationshipType;
28  import org.neo4j.graphdb.Traverser.Order;
29  import org.neo4j.graphdb.traversal.TraversalDescription;
30  import org.neo4j.kernel.Traversal;
31  
32  /*
33   * Maybe refactor to have a constructor with default stuff and make
34   * methods non-static
35   */
36  public class TraversalDescriptionBuilder
37  {
38      public static TraversalDescription from( Map<String, Object> description )
39      {
40          try
41          {
42              TraversalDescription result = Traversal.description();
43              result = describeOrder( result, description );
44              result = describeUniqueness( result, description );
45              result = describeRelationships( result, description );
46              result = describePruneEvaluator( result, description );
47              result = describeReturnFilter( result, description );
48              return result;
49          }
50          catch ( NoClassDefFoundError e )
51          {
52              // This one can happen if you run on Java 5, but haven't included the
53              // backported javax.script jar file(s) on the classpath.
54              throw new EvaluationException( e );
55          }
56      }
57  
58      @SuppressWarnings("unchecked")
59      private static TraversalDescription describeReturnFilter(
60              TraversalDescription result, Map<String, Object> description )
61      {
62          Object returnDescription = description.get( "return filter" );
63          if ( returnDescription != null )
64          {
65              result = result.filter( EvaluatorFactory.returnFilter( (Map) returnDescription ) );
66          }
67          else
68          {
69              // Default return evaluator
70              result = result.filter( Traversal.returnAllButStartNode() );
71          }
72          return result;
73      }
74  
75      @SuppressWarnings("unchecked")
76      private static TraversalDescription describePruneEvaluator(
77              TraversalDescription result, Map<String, Object> description )
78      {
79          Object pruneDescription = description.get( "prune evaluator" );
80          if ( pruneDescription != null )
81          {
82              result = result.prune( EvaluatorFactory.pruneEvaluator( (Map) pruneDescription ) );
83          }
84          
85          Object maxDepth = description.get( "max depth" );
86          maxDepth = maxDepth != null || pruneDescription != null ? maxDepth : 1;
87          if ( maxDepth != null )
88          {
89              result = result.prune( Traversal.pruneAfterDepth(
90                      ((Number) maxDepth).intValue() ) );
91          }
92          return result;
93      }
94  
95      @SuppressWarnings("unchecked")
96      private static TraversalDescription describeRelationships(
97              TraversalDescription result, Map<String, Object> description )
98      {
99          Object relationshipsDescription = description.get( "relationships" );
100         if ( relationshipsDescription != null )
101         {
102             Collection<Object> pairDescriptions;
103             if ( relationshipsDescription instanceof Collection )
104             {
105                 pairDescriptions = (Collection<Object>) relationshipsDescription;
106             }
107             else
108             {
109                 pairDescriptions = Arrays.asList( relationshipsDescription );
110             }
111             
112             for ( Object pairDescription : pairDescriptions )
113             {
114                 Map map = (Map) pairDescription;
115                 String name = (String) map.get( "type" );
116                 RelationshipType type = DynamicRelationshipType.withName( name );
117                 String directionName = (String) map.get( "direction" );
118                 result = directionName == null ? result.relationships( type ) :
119                         result.relationships( type, stringToEnum( directionName,
120                                 RelationshipDirection.class, true ).internal );
121             }
122         }
123         return result;
124     }
125 
126     private static TraversalDescription describeUniqueness(
127             TraversalDescription result, Map<String, Object> description )
128     {
129         Object uniquenessDescription = description.get( "uniqueness" );
130         if ( uniquenessDescription != null )
131         {
132             String name = null;
133             Object value = null;
134             if ( uniquenessDescription instanceof Map )
135             {
136                 Map map = (Map) uniquenessDescription;
137                 name = (String) map.get( "name" );
138                 value = map.get( "value" );
139             }
140             else
141             {
142                 name = (String) uniquenessDescription;
143             }
144             org.neo4j.kernel.Uniqueness uniqueness = stringToEnum( enumifyName( name ), org.neo4j.kernel.Uniqueness.class, true );
145             result = value == null ? result.uniqueness( uniqueness ) :
146                     result.uniqueness( uniqueness, value );
147         }
148         return result;
149     }
150 
151     private static TraversalDescription describeOrder(
152             TraversalDescription result, Map<String, Object> description )
153     {
154         String orderDescription = (String) description.get( "order" );
155         if ( orderDescription != null )
156         {
157             Order order = stringToEnum( enumifyName( orderDescription ), Order.class, true );
158             // TODO Fix
159             switch ( order )
160             {
161             case BREADTH_FIRST:
162                 result = result.breadthFirst();
163                 break;
164             case DEPTH_FIRST:
165                 result = result.depthFirst();
166                 break;
167             }
168         }
169         return result;
170     }
171 
172     private static <T extends Enum<T>> T stringToEnum( String name, Class<T> enumClass,
173             boolean fuzzyMatch )
174     {
175         if ( name == null )
176         {
177             return null;
178         }
179         
180 //        name = enumifyName( name );
181         for ( T candidate : enumClass.getEnumConstants() )
182         {
183             if ( candidate.name().equals( name ) )
184             {
185                 return candidate;
186             }
187         }
188         if ( fuzzyMatch )
189         {
190             for ( T candidate : enumClass.getEnumConstants() )
191             {
192                 if ( candidate.name().startsWith( name ) )
193                 {
194                     return candidate;
195                 }
196             }
197         }
198         throw new RuntimeException( "Unregognized " + enumClass.getSimpleName() + " '" +
199                 name + "'" );
200     }
201 
202     private static String enumifyName( String name )
203     {
204         return name.replaceAll( " ", "_" ).toUpperCase();
205     }
206 }