KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > exoplatform > services > jcr > impl > core > nodetype > NodeTypeImpl


1 /***************************************************************************
2  * Copyright 2001-2003 The eXo Platform SARL All rights reserved. *
3  * Please look at license.txt in info directory for more license detail. *
4  **************************************************************************/

5 package org.exoplatform.services.jcr.impl.core.nodetype;
6
7 import java.util.ArrayList JavaDoc;
8
9 import org.apache.commons.logging.Log;
10 import org.exoplatform.services.log.LogUtil;
11
12 import javax.jcr.Value;
13 import javax.jcr.PropertyType;
14 import javax.jcr.nodetype.*;
15
16 /**
17  * Created by The eXo Platform SARL .
18  *
19  * @author <a HREF="mailto:geaz@users.sourceforge.net">Gennady Azarenkov</a>
20  * @version $Id: NodeTypeImpl.java,v 1.21 2004/09/10 11:14:47 geaz Exp $
21  */

22 abstract public class NodeTypeImpl implements NodeType {
23
24   protected Log log;
25
26   protected String JavaDoc name;
27   protected boolean mixin;
28   protected NodeType[] declaredSupertypes;
29   protected PropertyDef[] declaredPropertyDefs;
30   protected NodeDef[] declaredNodeDefs;
31
32   public NodeTypeImpl() {
33     log = LogUtil.getLog("org.exoplatform.services.jcr");
34   }
35
36
37   /**
38    * 6.10.5
39    * Returns the name of the node type.
40    */

41   public String JavaDoc getName() {
42     return name;
43   }
44
45   /**
46    * Returns <code>true</code> if this node type is a mixin node type.
47    * Returns <code>false</code> if this node type is a primary node type.
48    *
49    * @return a boolean
50    */

51   public boolean isMixin() {
52     return mixin;
53   }
54
55   /**
56    * 6.10.5
57    * Returns all supertypes of this node in the node type
58    * inheritance hierarchy. This consists of all node types
59    * encountered as one ascends the hierarchy to the
60    * common base type nt:base.
61    */

62   public NodeType[] getSupertypes() {
63     ArrayList JavaDoc stypesList = new ArrayList JavaDoc();
64
65     fillSupertypes(stypesList, this);
66     if (stypesList.size() > 0) {
67       NodeType[] supertypes = new NodeType[stypesList.size()];
68       for (int i = 0; i < stypesList.size(); i++) {
69         supertypes[i] = (NodeType) stypesList.get(i);
70       }
71       return supertypes;
72     }
73     return new NodeType[0];
74   }
75
76   /**
77    * 6.10.5
78    * Returns the direct supertypes of this node in the node
79    * type inheritance hierarchy, that is, those actually
80    * declared in this node type. In single-inheritance
81    * systems, this will always be an array of size 0 or 1. In
82    * systems that support multiple inheritance of node types
83    * this array may be of size greater than 1.
84    * systems that support multiple inheritance of node types
85    * this array may be of size greater than 1.
86    */

87   public NodeType[] getDeclaredSupertypes() {
88     return declaredSupertypes;
89   }
90
91   /**
92    * 6.10.5
93    * Returns an array containing the property definitions of
94    * this node type. This includes both those property
95    * definitions actually declared in this node type and those
96    * inherited from the supertypes of this node type.
97    */

98   public PropertyDef[] getPropertyDefs() {
99     ArrayList JavaDoc propertyDefsList = new ArrayList JavaDoc();
100
101     if (declaredPropertyDefs != null) {
102       for (int i = 0; i < declaredPropertyDefs.length; i++) {
103         propertyDefsList.add(declaredPropertyDefs[i]);
104       }
105     }
106     NodeType[] supertypes = getSupertypes();
107     if (supertypes != null) {
108       for (int i = 0; i < supertypes.length; i++) {
109         if (supertypes[i].getDeclaredPropertyDefs() != null) {
110           for (int j = 0; j < supertypes[i].getDeclaredPropertyDefs().length; j++) {
111             if (!propertyDefsList.contains(supertypes[i].getDeclaredPropertyDefs()[j]))
112               propertyDefsList.add(supertypes[i].getDeclaredPropertyDefs()[j]);
113           }
114         }
115       }
116     }
117
118     if (propertyDefsList.size() > 0) {
119       PropertyDef[] propertyDefs = new PropertyDef[propertyDefsList.size()];
120       for (int i = 0; i < propertyDefsList.size(); i++) {
121         propertyDefs[i] = (PropertyDef) propertyDefsList.get(i);
122       }
123       return propertyDefs;
124     }
125     return null;
126   }
127
128   /**
129    * 6.10.5
130    * Returns an array containing the property definitions
131    * actually declared in this node type.
132    */

133   public PropertyDef[] getDeclaredPropertyDefs() {
134     return declaredPropertyDefs;
135   }
136
137   /**
138    * 6.10.5
139    * Returns an array containing the child node definitions of
140    * this node type. This includes both those child node
141    * definitions actually declared in this node type and those
142    * inherited from the supertypes of this node type.
143    */

144   public NodeDef[] getChildNodeDefs() {
145     ArrayList JavaDoc nodeDefsList = new ArrayList JavaDoc();
146
147     if (declaredNodeDefs != null)
148       for (int i = 0; i < declaredNodeDefs.length; i++)
149         nodeDefsList.add(declaredNodeDefs[i]);
150
151     NodeType[] supertypes = getSupertypes();
152     if (supertypes != null) {
153       for (int i = 0; i < supertypes.length; i++) {
154         if (supertypes[i].getDeclaredChildNodeDefs() != null) {
155           for (int j = 0; j < supertypes[i].getDeclaredChildNodeDefs().length; j++) {
156             if (!nodeDefsList.contains(supertypes[i].getDeclaredChildNodeDefs()[j])) {
157               nodeDefsList.add(supertypes[i].getDeclaredChildNodeDefs()[j]);
158             }
159           }
160         }
161       }
162     }
163
164     if (nodeDefsList.size() > 0) {
165       NodeDef[] childNodeDefs = new NodeDef[nodeDefsList.size()];
166       for (int i = 0; i < nodeDefsList.size(); i++) {
167         childNodeDefs[i] = (NodeDef) nodeDefsList.get(i);
168       }
169       return childNodeDefs;
170     }
171     return new NodeDef[0];
172   }
173
174   /**
175    * 6.10.5
176    * Returns an array containing the child node definitions
177    * actually declared in this node type.
178    */

179   public NodeDef[] getDeclaredChildNodeDefs() {
180     return declaredNodeDefs;
181   }
182
183   /**
184    * Returns <code>true</code> if setting <code>propertyName</code> to
185    * <code>value</code> is allowed by this node type. Otherwise returns
186    * <code>false</code>.
187    *
188    * @param propertyName The name of the property
189    * @param value A <code>Value</code> object.
190    */

191   public boolean canSetProperty(String JavaDoc propertyName, Value value) {
192     try {
193       checkSetProperty(propertyName, value);
194       return true;
195     } catch (ConstraintViolationException e) {
196       return false;
197     }
198   }
199
200   /**
201    * Returns <code>true</code> Checks if adding a child node called
202    * <code>childNodeName</code> is allowed by <i>this</i> node type.
203    * <p/>
204    *
205    * @param childNodeName The name of the child node.
206    */

207   public boolean canAddChildNode(String JavaDoc childNodeName) {
208     try {
209       checkAddChildNode(childNodeName);
210       return true;
211     } catch (ConstraintViolationException e) {
212       return false;
213     }
214   }
215
216   /**
217    * Returns <code>true</code> if adding a child node called
218    * <code>childNodeName</code> of node type <code>nodeTypeName</code> is
219    * allowed by <i>this</i> node type. Otherwise returns <code>false</code>.
220    * The same as <code>{@link #canAddChildNode(String childNodeName)}</code>
221    * except that the type of the child node is explictly specified.
222    *
223    * @param childNodeName The name of the child node.
224    * @param nodeTypeName The name of the node type of the child node.
225    */

226   public boolean canAddChildNode(String JavaDoc childNodeName, String JavaDoc nodeTypeName) {
227     try {
228       checkAddChildNode(childNodeName, nodeTypeName);
229       return true;
230     } catch (ConstraintViolationException e) {
231       return false;
232     }
233   }
234
235   /**
236    * Returns true if removing <code>itemName</code> is allowed by this node type.
237    * Otherwise returns <code>false</code>.
238    *
239    * @param itemName The name of the child item
240    */

241   public boolean checkRemoveItem(String JavaDoc itemName) {
242     try {
243       checkRemove(itemName);
244       return true;
245     } catch (ConstraintViolationException e) {
246       return false;
247     }
248   }
249
250   public PropertyDef getPropertyDef(String JavaDoc name) {
251     int residualNb = 0;
252     PropertyDef residualProperty = null;
253     for (int i = 0; i < getPropertyDefs().length; i++) {
254       PropertyDef prop = getPropertyDefs()[i];
255       if (prop.getName() != null) {
256         if (prop.getName().equals(name))
257           return prop;
258       } else {
259         // residual def
260
residualNb++;
261         residualProperty = prop;
262       }
263     }
264     if (residualNb == 1)
265       return residualProperty;
266     return null;
267   }
268
269
270   public NodeDef getChildNodeDef(String JavaDoc name) {
271     NodeDef[] nodeDefs = getChildNodeDefs();
272     for (int i = 0; i < nodeDefs.length; i++) {
273       NodeDef nodeDef = getChildNodeDefs()[i];
274       if (nodeDef.getName() != null) {
275         if (nodeDef.getName().equals(name))
276           return nodeDef;
277       }
278     }
279
280     // Residual def
281
for (int i = 0; i < nodeDefs.length; i++) {
282       NodeDef nodeDef = nodeDefs[i];
283       if (nodeDef.getName() == null) {
284         return nodeDef;
285       }
286     }
287     return null;
288   }
289
290   public String JavaDoc toString() {
291     return "NodeType: " + name;
292   }
293
294   public boolean equals(Object JavaDoc obj) {
295     if (!(obj instanceof NodeTypeImpl))
296       return false;
297     return name == ((NodeType) obj).getName();
298   }
299
300
301   /**
302    * 6.10.5
303    * Checks if setting propertyName to value is allowed by
304    * this node type. If it is not allowed a
305    * ConstraintViolationException is thrown.
306    */

307   public void checkSetProperty(String JavaDoc propertyName, Value value) throws ConstraintViolationException {
308     boolean residualFlag = false;
309     for (int i = 0; i < getPropertyDefs().length; i++) {
310       PropertyDef prop = getPropertyDefs()[i];
311       if (prop.getName() == null) {
312         residualFlag = true;
313       } else if (prop.getName().equals(propertyName)) {
314         if (prop.isReadOnly())
315           throw new ConstraintViolationException("Could not set Read-Only Property <" + propertyName + "> !");
316         if (prop.getRequiredType() != PropertyType.UNDEFINED
317             && value.getType() != prop.getRequiredType())
318           throw new ConstraintViolationException("Invalid required property type <" +
319               prop.getRequiredType() + "> for Property <" + propertyName + "> !");
320         if (!checkValueConstraint(prop.getValueConstraint(), value))
321           throw new ConstraintViolationException("Value Constraint <" + prop.getValueConstraint()
322               + "> violated for Property <" + propertyName + "> !");
323         if (prop.getName().indexOf("[") > -1 && !prop.isMultiple())
324           throw new ConstraintViolationException("Multiplicity is not supported for Property <"
325               + propertyName + "> !");
326         return;
327       }
328     }
329     if (residualFlag)
330       return;
331     else
332       throw new ConstraintViolationException("Property <" + propertyName + "> is not allowed!");
333
334   }
335
336   /**
337    * 6.10.5
338    * Checks if adding a child node called childNodeName of
339    * is allowed by this node type. If it is not allowed or if the
340    * node type of the child node cannot be unambiguously
341    * determined than a ConstraintViolationException is thrown.
342    */

343   public void checkAddChildNode(String JavaDoc childNodeName) throws ConstraintViolationException {
344     checkAddChildNode(childNodeName, null);
345   }
346
347   /**
348    * 6.10.5
349    * Checks if adding a child node called childNodeName of
350    * node type nodeTypeName is allowed by this node type.
351    * The same as checkAddChildNode(String childNodeName)
352    * except that the type of the child node is explicitly
353    * specified. If it is not allowed, a
354    * ConstraintViolationException is thrown.
355    */

356   public void checkAddChildNode(String JavaDoc childNodeName, String JavaDoc nodeTypeName) throws ConstraintViolationException {
357     if (getChildNodeDefs() == null)
358       throw new ConstraintViolationException("Node <" + childNodeName + "> is not allowed!");
359
360     int residual = 0;
361     NodeDef residualDef = null;
362
363     for (int i = 0; i < getChildNodeDefs().length; i++) {
364       NodeDef def = getChildNodeDefs()[i];
365       if (def.getName() == null) {
366         residualDef = def;
367         residual++;
368       } else if (def.getName().equals(childNodeName)) {
369         if (def.isReadOnly()) {
370           log.debug("NodeType.checkAddChildNode(): Could not add Read-Only Node <" + childNodeName + "> !");
371           throw new ConstraintViolationException("NodeType.checkAddChildNode(): Could not add Read-Only Node <" + childNodeName + "> !");
372         }
373
374         if (def.getName().indexOf("[") > -1 && !def.allowSameNameSibs()) {
375           log.debug("NodeType.checkAddChildNode(): Multiplicity is not supported for Node <" + childNodeName + "> !");
376           throw new ConstraintViolationException("NodeType.checkAddChildNode(): Multiplicity is not supported for Node <" + childNodeName + "> !");
377         }
378
379         if (nodeTypeName != null) {
380           NodeDef[] childNodeDefs = getChildNodeDefs();
381           for (int j = 0; j < childNodeDefs.length; j++) {
382             NodeDef childNodeDef = childNodeDefs[j];
383             NodeType requiredNodeType = childNodeDef.getDefaultPrimaryType();
384             if (nodeTypeName.equals(requiredNodeType.getName())) {
385               return;
386             }
387           }
388           log.debug("NodeType.checkAddChildNode(): Incompatible node type <" + nodeTypeName + ">");
389           throw new ConstraintViolationException("NodeType.checkAddChildNode(): Incompatible node type <" + nodeTypeName + ">");
390         }
391       }
392     }
393     if (residual == 1) {
394       if (nodeTypeName != null) {
395         NodeType[] requiredNodeTypes = residualDef.getRequiredPrimaryTypes();
396         for (int i = 0; i < requiredNodeTypes.length; i++) {
397           String JavaDoc residualNodeTypeName = requiredNodeTypes[i].getName();
398
399           NodeType testNodeType;
400           try {
401               testNodeType = NodeTypeManagerImpl.getInstance().getNodeType(nodeTypeName);
402            } catch (NoSuchNodeTypeException e) {
403               throw new ConstraintViolationException("No such node: "+nodeTypeName);
404            }
405
406           if (isSameOrSubType(requiredNodeTypes[i], testNodeType))
407             return;
408           log.debug("NodeType.checkAddChildNode(): Incompatible node type for residual(1) <" + nodeTypeName + ">");
409           throw new ConstraintViolationException("NodeType.checkAddChildNode(): Incompatible node type for residual <" + nodeTypeName + ">");
410         }
411       }
412     } else if (residual > 1) {
413       if (nodeTypeName != null) {
414         for (int i = 0; i < getChildNodeDefs().length; i++) {
415           NodeDef def = getChildNodeDefs()[i];
416           if (def.getName() == null) {
417             if (nodeTypeName.equals(def.getDeclaringNodeType().getName()))
418               return;
419           }
420         }
421       }
422       log.debug("NodeType.checkAddChildNode(): Incompatible node type for residual>0 <" + nodeTypeName + ">");
423       throw new ConstraintViolationException("NodeType.checkAddChildNode(): Incompatible node type for residual>0 <" + nodeTypeName + ">");
424     } else {
425       log.debug("NodeType.checkAddChildNode(): Node <" + childNodeName + "> is not allowed!");
426       throw new ConstraintViolationException("NodeType.checkAddChildNode(): Node <" + childNodeName + "> is not allowed!");
427     }
428
429   }
430
431   /**
432    * 6.10.5
433    * Checks if removing itemName is allowed by this node
434    * type. If it is not allowed a ConstraintViolationException is thrown.
435    */

436   public void checkRemove(String JavaDoc childNodeName) throws ConstraintViolationException {
437
438     boolean residualFlag = false;
439
440     for (int i = 0; i < getChildNodeDefs().length; i++) {
441       NodeDef def = getChildNodeDefs()[i];
442       if (def.getName() == null) {
443         residualFlag = true;
444       } else if (def.getName().equals(childNodeName)) {
445         if (def.isReadOnly())
446           throw new ConstraintViolationException("Could not remove Read-Only Node <" + childNodeName + "> !");
447         if (def.isMandatory())
448           throw new ConstraintViolationException("Could not remove Mandatory Node <" + childNodeName + "> !");
449       }
450     }
451     if (residualFlag)
452       return;
453     else
454       throw new ConstraintViolationException("Node <" + childNodeName + "> is not allowed!");
455
456   }
457
458   protected boolean isBase() {
459     return getSupertypes().length == 0;
460   }
461
462   protected boolean checkValueConstraint(String JavaDoc constraint, Value value) {
463     return true;
464   }
465
466   protected void fillSupertypes(ArrayList JavaDoc list, NodeType subtype) {
467     if (subtype.getDeclaredSupertypes() != null) {
468       for (int i = 0; i < subtype.getDeclaredSupertypes().length; i++) {
469         list.add(subtype.getDeclaredSupertypes()[i]);
470         fillSupertypes(list, subtype.getDeclaredSupertypes()[i]);
471       }
472     }
473
474   }
475
476   public static boolean isSameOrSubType(NodeType superType, NodeType subType) {
477     if (superType.getName().equals(subType.getName()))
478       return true;
479     else {
480
481       NodeType[] superTypes = subType.getSupertypes();
482 /*
483       try {
484         superTypes = NodeTypeManagerImpl.getInstance().getNodeType(typeName).getSupertypes();
485       } catch (NoSuchNodeTypeException e) {
486 // log.error("NodeTypeImpl.isSameOrSubTypeName() error " + e);
487         return false;
488       }
489 */

490       for (int j = 0; j < superTypes.length; j++) {
491         NodeType testSuperType = superTypes[j];
492         if (testSuperType.getName().equals(superType.getName()))
493           return true;
494       }
495     }
496     return false;
497   }
498
499 }
500
Popular Tags