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.jcr;
25  
26  import java.util.ArrayList;
27  import java.util.List;
28  import javax.jcr.nodetype.ConstraintViolationException;
29  import javax.jcr.nodetype.NodeDefinition;
30  import javax.jcr.nodetype.PropertyDefinition;
31  import net.jcip.annotations.NotThreadSafe;
32  import org.modeshape.common.util.CheckArg;
33  import org.modeshape.graph.ExecutionContext;
34  import org.modeshape.graph.property.Name;
35  import org.modeshape.graph.property.ValueFormatException;
36  import org.modeshape.jcr.nodetype.NodeDefinitionTemplate;
37  import org.modeshape.jcr.nodetype.NodeTypeDefinition;
38  import org.modeshape.jcr.nodetype.NodeTypeTemplate;
39  import org.modeshape.jcr.nodetype.PropertyDefinitionTemplate;
40  
41  /**
42   * ModeShape implementation of the JCR NodeTypeTemplate interface
43   */
44  @NotThreadSafe
45  public class JcrNodeTypeTemplate implements NodeTypeDefinition, NodeTypeTemplate {
46  
47      private final ExecutionContext context;
48      private final List<NodeDefinitionTemplate> nodeDefinitionTemplates = new ArrayList<NodeDefinitionTemplate>();
49      private final List<PropertyDefinitionTemplate> propertyDefinitionTemplates = new ArrayList<PropertyDefinitionTemplate>();
50      private final boolean createdFromExistingDefinition;
51      private boolean isAbstract;
52      private boolean queryable = true;
53      private boolean mixin;
54      private boolean orderableChildNodes;
55      private Name[] declaredSupertypeNames;
56      private Name name;
57      private Name primaryItemName;
58  
59      JcrNodeTypeTemplate( ExecutionContext context ) {
60          this(context, false);
61      }
62  
63      JcrNodeTypeTemplate( ExecutionContext context,
64                           boolean createdFromExistingDefinition ) {
65          assert context != null;
66  
67          this.context = context;
68          this.createdFromExistingDefinition = createdFromExistingDefinition;
69      }
70  
71      JcrNodeTypeTemplate( JcrNodeTypeTemplate original,
72                           ExecutionContext context ) {
73          this.context = context;
74          this.isAbstract = original.isAbstract;
75          this.queryable = original.queryable;
76          this.mixin = original.mixin;
77          this.name = original.name;
78          this.orderableChildNodes = original.orderableChildNodes;
79          this.declaredSupertypeNames = original.declaredSupertypeNames;
80          this.primaryItemName = original.primaryItemName;
81          JcrItemDefinitionTemplate.registerMissingNamespaces(original.context, context, this.name);
82          JcrItemDefinitionTemplate.registerMissingNamespaces(original.context, context, this.declaredSupertypeNames);
83          JcrItemDefinitionTemplate.registerMissingNamespaces(original.context, context, this.primaryItemName);
84          for (NodeDefinitionTemplate childDefn : original.nodeDefinitionTemplates) {
85              this.nodeDefinitionTemplates.add(((JcrNodeDefinitionTemplate)childDefn).with(context));
86          }
87          for (PropertyDefinitionTemplate propDefn : original.propertyDefinitionTemplates) {
88              this.propertyDefinitionTemplates.add(((JcrPropertyDefinitionTemplate)propDefn).with(context));
89          }
90          this.createdFromExistingDefinition = original.createdFromExistingDefinition;
91      }
92  
93      JcrNodeTypeTemplate with( ExecutionContext context ) {
94          return context == this.context ? this : new JcrNodeTypeTemplate(this, context);
95      }
96  
97      ExecutionContext getExecutionContext() {
98          return context;
99      }
100 
101     private String string( Name name ) {
102         if (name == null) return null;
103         return name.getString(context.getNamespaceRegistry());
104     }
105 
106     Name[] declaredSupertypeNames() {
107         return this.declaredSupertypeNames;
108     }
109 
110     /**
111      * {@inheritDoc}
112      * 
113      * @see org.modeshape.jcr.nodetype.NodeTypeTemplate#getNodeDefinitionTemplates()
114      */
115     public List<NodeDefinitionTemplate> getNodeDefinitionTemplates() {
116         return nodeDefinitionTemplates;
117     }
118 
119     /**
120      * {@inheritDoc}
121      * 
122      * @see org.modeshape.jcr.nodetype.NodeTypeTemplate#getPropertyDefinitionTemplates()
123      */
124     public List<PropertyDefinitionTemplate> getPropertyDefinitionTemplates() {
125         return propertyDefinitionTemplates;
126     }
127 
128     /**
129      * {@inheritDoc}
130      * 
131      * @see org.modeshape.jcr.nodetype.NodeTypeTemplate#setAbstract(boolean)
132      */
133     public void setAbstract( boolean isAbstract ) {
134         this.isAbstract = isAbstract;
135     }
136 
137     /**
138      * Set the direct supertypes for this node type.
139      * 
140      * @param names the names of the direct supertypes, or empty or null if there are none.
141      * @throws ConstraintViolationException
142      */
143     public void setDeclaredSuperTypeNames( String[] names ) throws ConstraintViolationException {
144         if (names == null) {
145             throw new ConstraintViolationException(JcrI18n.badNodeTypeName.text("names"));
146         }
147 
148         Name[] supertypeNames = new Name[names.length];
149 
150         for (int i = 0; i < names.length; i++) {
151             CheckArg.isNotEmpty(names[i], "names[" + i + "");
152             try {
153                 supertypeNames[i] = context.getValueFactories().getNameFactory().create(names[i]);
154             } catch (ValueFormatException vfe) {
155                 throw new ConstraintViolationException(vfe);
156             }
157         }
158         this.declaredSupertypeNames = supertypeNames;
159     }
160 
161     /**
162      * {@inheritDoc}
163      * 
164      * @see org.modeshape.jcr.nodetype.NodeTypeTemplate#setMixin(boolean)
165      */
166     public void setMixin( boolean mixin ) {
167         this.mixin = mixin;
168     }
169 
170     /**
171      * {@inheritDoc}
172      * 
173      * @see org.modeshape.jcr.nodetype.NodeTypeTemplate#setName(java.lang.String)
174      */
175     public void setName( String name ) throws ConstraintViolationException {
176         CheckArg.isNotEmpty(name, "name");
177         try {
178             this.name = context.getValueFactories().getNameFactory().create(name);
179         } catch (ValueFormatException vfe) {
180             throw new ConstraintViolationException(vfe);
181         }
182     }
183 
184     /**
185      * {@inheritDoc}
186      * 
187      * @see org.modeshape.jcr.nodetype.NodeTypeTemplate#setOrderableChildNodes(boolean)
188      */
189     public void setOrderableChildNodes( boolean orderable ) {
190         this.orderableChildNodes = orderable;
191     }
192 
193     /**
194      * {@inheritDoc}
195      * <p>
196      * Passing a null or blank name is equivalent to "unsetting" (or removing) the primary item name.
197      * </p>
198      * 
199      * @see org.modeshape.jcr.nodetype.NodeTypeDefinition#getPrimaryItemName()
200      *      type.NodeTypeTemplate#setPrimaryItemName(java.lang.String)
201      */
202     public void setPrimaryItemName( String name ) throws ConstraintViolationException {
203         if (name == null || name.trim().length() == 0) {
204             this.primaryItemName = null;
205         } else {
206             try {
207                 this.primaryItemName = context.getValueFactories().getNameFactory().create(name);
208             } catch (ValueFormatException vfe) {
209                 throw new ConstraintViolationException(vfe);
210             }
211         }
212     }
213 
214     /**
215      * {@inheritDoc}
216      * 
217      * @see NodeTypeDefinition#getDeclaredChildNodeDefinitions()
218      */
219     public NodeDefinition[] getDeclaredChildNodeDefinitions() {
220         if (!createdFromExistingDefinition && nodeDefinitionTemplates.isEmpty()) return null;
221 
222         return nodeDefinitionTemplates.toArray(new NodeDefinition[nodeDefinitionTemplates.size()]);
223     }
224 
225     /**
226      * {@inheritDoc}
227      * 
228      * @see org.modeshape.jcr.nodetype.NodeTypeDefinition#getDeclaredPropertyDefinitions()
229      */
230     public PropertyDefinition[] getDeclaredPropertyDefinitions() {
231         if (!createdFromExistingDefinition && propertyDefinitionTemplates.isEmpty()) return null;
232 
233         return propertyDefinitionTemplates.toArray(new PropertyDefinition[propertyDefinitionTemplates.size()]);
234     }
235 
236     /**
237      * Get the direct supertypes for this node type.
238      * 
239      * @return the names of the direct supertypes, or an empty array if there are none
240      */
241     public String[] getDeclaredSupertypeNames() {
242         if (declaredSupertypeNames == null) return new String[0];
243         String[] names = new String[declaredSupertypeNames.length];
244 
245         for (int i = 0; i < declaredSupertypeNames.length; i++) {
246             names[i] = declaredSupertypeNames[i].getString(context.getNamespaceRegistry());
247         }
248         return names;
249     }
250 
251     /**
252      * {@inheritDoc}
253      * 
254      * @see org.modeshape.jcr.nodetype.NodeTypeDefinition#getName()
255      */
256     public String getName() {
257         return string(name);
258     }
259 
260     /**
261      * {@inheritDoc}
262      * 
263      * @see org.modeshape.jcr.nodetype.NodeTypeDefinition#getPrimaryItemName()
264      */
265     public String getPrimaryItemName() {
266         return string(primaryItemName);
267     }
268 
269     /**
270      * {@inheritDoc}
271      * 
272      * @see org.modeshape.jcr.nodetype.NodeTypeDefinition#hasOrderableChildNodes()
273      */
274     public boolean hasOrderableChildNodes() {
275         return orderableChildNodes;
276     }
277 
278     /**
279      * {@inheritDoc}
280      * 
281      * @see org.modeshape.jcr.nodetype.NodeTypeDefinition#isAbstract()
282      */
283     public boolean isAbstract() {
284         return isAbstract;
285     }
286 
287     /**
288      * {@inheritDoc}
289      * 
290      * @see org.modeshape.jcr.nodetype.NodeTypeDefinition#isMixin()
291      */
292     public boolean isMixin() {
293         return mixin;
294     }
295 
296     /**
297      * Get whether this node is queryable
298      * 
299      * @return true if the node is queryable; false otherwise
300      */
301     public boolean isQueryable() {
302         return queryable;
303     }
304 
305     /**
306      * {@inheritDoc}
307      * 
308      * @see org.modeshape.jcr.nodetype.NodeTypeTemplate#setQueryable(boolean)
309      */
310     public void setQueryable( boolean queryable ) {
311         this.queryable = queryable;
312     }
313 }