View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors.
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   * 
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.sequencer.ddl.node;
25  
26  import java.util.ArrayList;
27  import java.util.List;
28  import org.modeshape.graph.ExecutionContext;
29  import org.modeshape.graph.JcrLexicon;
30  import org.modeshape.graph.JcrNtLexicon;
31  import org.modeshape.graph.property.Name;
32  import org.modeshape.graph.property.Path;
33  import org.modeshape.graph.property.Property;
34  import org.modeshape.graph.property.basic.LongValueFactory;
35  import org.modeshape.graph.property.basic.SimpleNamespaceRegistry;
36  import org.modeshape.graph.property.basic.StringValueFactory;
37  
38  /**
39   * Utility class which provides construction, editing and assorted methods to work with AstNodes.
40   */
41  public class AstNodeFactory {
42      /**
43       * The context responsible for maintaining a consistent unique set of graph and node properties. see {@link ExecutionContext}
44       */
45      private ExecutionContext context;
46  
47      private LongValueFactory longFactory;
48      private StringValueFactory stringFactory;
49  
50      /**
51       * @param context
52       */
53      public AstNodeFactory( ExecutionContext context ) {
54          super();
55          this.context = context;
56          this.stringFactory = new StringValueFactory(new SimpleNamespaceRegistry(), Path.URL_DECODER, Path.URL_ENCODER);
57          this.longFactory = new LongValueFactory(Path.URL_DECODER, stringFactory);
58      }
59  
60      public AstNodeFactory() {
61          this.context = new ExecutionContext();
62      }
63  
64      /**
65       * Constructs a {@link Name} with the given string name
66       * 
67       * @param name the name to use in constructing a {@link Name} instance; may not be null
68       * @return name the {@link Name} graph property object
69       */
70      public Name name( String name ) {
71          assert name != null;
72          return context.getValueFactories().getNameFactory().create(name);
73      }
74  
75      /**
76       * Constructs an {@link AstNode} with the given string name
77       * 
78       * @param name the name property of the node; may not be null
79       * @return the tree node
80       */
81      public AstNode node( String name ) {
82          assert name != null;
83  
84          AstNode node = new AstNode(name(name));
85          node.setProperty(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.UNSTRUCTURED);
86  
87          return node;
88      }
89  
90      /**
91       * Constructs an {@link AstNode} with the given name, types and parent node.
92       * 
93       * @param name the name property of the node; may not be null
94       * @param parent the parent of the node; may not be null
95       * @param types the list of mixin types {@link Name} for the requested node; may not be null or empty
96       * @return the tree node
97       */
98      public AstNode node( String name,
99                           AstNode parent,
100                          Object... types ) {
101         assert name != null;
102         assert parent != null;
103         assert types != null;
104         assert types.length > 0;
105 
106         AstNode node = new AstNode(name(name));
107         node.setProperty(JcrLexicon.MIXIN_TYPES, types);
108         node.setProperty(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.UNSTRUCTURED);
109         node.setParent(parent);
110         return node;
111     }
112 
113     /**
114      * Constructs an {@link AstNode} with the given name, type and parent node.
115      * 
116      * @param name the name property of the node; may not be null
117      * @param parent the parent of the node; may not be null
118      * @param type the mixin type {@link Name} for the requested node; may not be null
119      * @return the tree node
120      */
121     public AstNode node( String name,
122                          AstNode parent,
123                          Name type ) {
124         assert name != null;
125         assert parent != null;
126         assert type != null;
127 
128         AstNode node = new AstNode(name(name));
129         node.setProperty(JcrLexicon.MIXIN_TYPES, type);
130         node.setProperty(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.UNSTRUCTURED);
131         node.setParent(parent);
132         return node;
133     }
134 
135     /**
136      * Sets the mixin type property for an {@link AstNode}
137      * 
138      * @param node the node to set the property on; may not be null
139      * @param type the mixin type {@link Name}; may not be null
140      */
141     public void setType( AstNode node,
142                          Name type ) {
143         assert node != null;
144         assert type != null;
145         node.setProperty(JcrLexicon.MIXIN_TYPES, type);
146     }
147 
148     /**
149      * Utility method to obtain the children of a given node that match the given type
150      * 
151      * @param astNode the parent node; may not be null
152      * @param nodeType the type property of the target child node; may not be null
153      * @return the list of typed nodes (may be empty)
154      */
155     public List<AstNode> getChildrenForType( AstNode astNode,
156                                              Name nodeType ) {
157         assert astNode != null;
158         assert nodeType != null;
159 
160         List<AstNode> childrenOfType = new ArrayList<AstNode>();
161         for (AstNode child : astNode.getChildren()) {
162             if (hasMixinType(child, nodeType)) {
163                 childrenOfType.add(child);
164             }
165         }
166 
167         return childrenOfType;
168     }
169 
170     /**
171      * Utility method to obtain a {@link AstNode} child of a parent {@link AstNode} with the given string name and node type.
172      * 
173      * @param astNode the parent node; may not be null
174      * @param name the name property of the node; may not be null
175      * @param nodeType the type property of the target child node; may not be null
176      * @return the matched child (may be null)
177      */
178     public AstNode getChildforNameAndType( AstNode astNode,
179                                            String name,
180                                            Name nodeType ) {
181         assert astNode != null;
182         assert name != null;
183         assert nodeType != null;
184 
185         for (AstNode child : astNode.getChildren()) {
186             if (hasMixinType(child.getProperty(JcrLexicon.MIXIN_TYPES), nodeType)) {
187                 if (name.equalsIgnoreCase(child.getName().getString())) {
188                     return child;
189                 }
190             }
191         }
192         return null;
193     }
194 
195     /**
196      * Utility method to determine if a list of input mixin {@link Property}s contains a specific mixin type.
197      * 
198      * @param mixins a list of mixin {@link Property} objects; may not be null
199      * @param mixinType the target mixin type; may not be null
200      * @return true if the mixinType exists in the property list.
201      */
202     private boolean hasMixinType( Property mixins,
203                                   Name mixinType ) {
204         assert mixins != null;
205         assert mixinType != null;
206 
207         for (Object prop : mixins.getValuesAsArray()) {
208             if (prop instanceof Name) {
209                 if (prop.equals(mixinType)) {
210                     return true;
211                 }
212             }
213         }
214 
215         return false;
216     }
217 
218     /**
219      * Utility method to determine if an {@link AstNode} contains a specific mixin type.
220      * 
221      * @param node the AstNode
222      * @param mixinType the target mixin type {@link Name}; may not be null;
223      * @return true if the mixinType exists for this node
224      */
225     public boolean hasMixinType( AstNode node,
226                                  Name mixinType ) {
227         assert node != null;
228         assert mixinType != null;
229         return hasMixinType(node.getProperty(JcrLexicon.MIXIN_TYPES), mixinType);
230     }
231 
232     public int createInt( String stringValue ) {
233         return longFactory.create(stringValue).intValue();
234     }
235 
236 }