KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > jcr > dictionary > NodeTypeImpl


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.jcr.dictionary;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Map JavaDoc;
22
23 import javax.jcr.PropertyType;
24 import javax.jcr.RepositoryException;
25 import javax.jcr.Value;
26 import javax.jcr.nodetype.NodeDefinition;
27 import javax.jcr.nodetype.NodeType;
28 import javax.jcr.nodetype.PropertyDefinition;
29
30 import org.alfresco.jcr.item.ValueImpl;
31 import org.alfresco.jcr.item.property.JCRMixinTypesProperty;
32 import org.alfresco.jcr.item.property.JCRPrimaryTypeProperty;
33 import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
34 import org.alfresco.service.cmr.dictionary.ClassDefinition;
35 import org.alfresco.service.cmr.dictionary.DictionaryService;
36 import org.alfresco.service.namespace.QName;
37
38 /**
39  * Alfresco implementation of a Node Type Definition
40  *
41  * @author David Caruana
42  */

43 public class NodeTypeImpl implements NodeType
44 {
45     // The required nt:base type specified by JCR
46
public static QName NT_BASE = QName.createQName(JCRNamespace.NT_URI, "base");
47
48     // The optional mix:referenceable specified by JCR
49
public static QName MIX_REFERENCEABLE = QName.createQName(JCRNamespace.MIX_URI, "referenceable");
50     // The optional mix:lockable specified by JCR
51
public static QName MIX_LOCKABLE = QName.createQName(JCRNamespace.MIX_URI, "lockable");
52     // The optional mix:versionable specified by JCR
53
public static QName MIX_VERSIONABLE = QName.createQName(JCRNamespace.MIX_URI, "versionable");
54
55     
56     private NodeTypeManagerImpl typeManager;
57     private ClassDefinition classDefinition;
58
59     
60     /**
61      * Construct
62      *
63      * @param classDefinition Alfresco class definition
64      */

65     public NodeTypeImpl(NodeTypeManagerImpl typeManager, ClassDefinition classDefinition)
66     {
67         this.typeManager = typeManager;
68         this.classDefinition = classDefinition;
69     }
70
71     /* (non-Javadoc)
72      * @see javax.jcr.nodetype.NodeType#getName()
73      */

74     public String JavaDoc getName()
75     {
76         return classDefinition.getName().toPrefixString(typeManager.getNamespaceService());
77     }
78
79     /* (non-Javadoc)
80      * @see javax.jcr.nodetype.NodeType#isMixin()
81      */

82     public boolean isMixin()
83     {
84         return classDefinition.isAspect();
85     }
86
87     /* (non-Javadoc)
88      * @see javax.jcr.nodetype.NodeType#hasOrderableChildNodes()
89      */

90     public boolean hasOrderableChildNodes()
91     {
92         // Note: For now, we don't expose this through JCR
93
return false;
94     }
95
96     /* (non-Javadoc)
97      * @see javax.jcr.nodetype.NodeType#getPrimaryItemName()
98      */

99     public String JavaDoc getPrimaryItemName()
100     {
101         // NOTE: Alfresco does not support the notion of PrimaryItem (not yet anyway)
102
return null;
103     }
104
105     /* (non-Javadoc)
106      * @see javax.jcr.nodetype.NodeType#getSupertypes()
107      */

108     public NodeType[] getSupertypes()
109     {
110         List JavaDoc<NodeType> nodeTypes = new ArrayList JavaDoc<NodeType>();
111         NodeType[] declaredSupertypes = getDeclaredSupertypes();
112         while (declaredSupertypes.length > 0)
113         {
114             // Alfresco supports single inheritence only
115
NodeType supertype = declaredSupertypes[0];
116             nodeTypes.add(supertype);
117             declaredSupertypes = supertype.getDeclaredSupertypes();
118         }
119         return nodeTypes.toArray(new NodeType[nodeTypes.size()]);
120     }
121
122     /* (non-Javadoc)
123      * @see javax.jcr.nodetype.NodeType#getDeclaredSupertypes()
124      */

125     public NodeType[] getDeclaredSupertypes()
126     {
127         // return no supertype when type is nt:base
128
if (classDefinition.getName().equals(NT_BASE))
129         {
130             return new NodeType[] {};
131         }
132         
133         // return root type when no parent (nt:base if a type hierarchy)
134
QName parent = classDefinition.getParentName();
135         if (parent == null)
136         {
137             if (classDefinition.isAspect())
138             {
139                 return new NodeType[] {};
140             }
141             else
142             {
143                 return new NodeType[] { typeManager.getNodeTypeImpl(NT_BASE) };
144             }
145         }
146         
147         // return the supertype
148
return new NodeType[] { typeManager.getNodeTypeImpl(parent) };
149     }
150
151     /* (non-Javadoc)
152      * @see javax.jcr.nodetype.NodeType#isNodeType(java.lang.String)
153      */

154     public boolean isNodeType(String JavaDoc nodeTypeName)
155     {
156         QName name = QName.createQName(nodeTypeName, typeManager.getNamespaceService());
157         
158         // is it one of standard types
159
if (name.equals(NodeTypeImpl.NT_BASE))
160         {
161             return true;
162         }
163
164         // is it part of this class hierarchy
165
return typeManager.getSession().getRepositoryImpl().getServiceRegistry().getDictionaryService().isSubClass(name, classDefinition.getName());
166     }
167
168     /* (non-Javadoc)
169      * @see javax.jcr.nodetype.NodeType#getPropertyDefinitions()
170      */

171     public PropertyDefinition[] getPropertyDefinitions()
172     {
173         Map JavaDoc<QName, org.alfresco.service.cmr.dictionary.PropertyDefinition> propDefs = classDefinition.getProperties();
174         PropertyDefinition[] defs = new PropertyDefinition[propDefs.size() + (classDefinition.isAspect() ? 0 : 2)];
175         int i = 0;
176         for (org.alfresco.service.cmr.dictionary.PropertyDefinition propDef : propDefs.values())
177         {
178             defs[i++] = new PropertyDefinitionImpl(typeManager, propDef);
179         }
180         
181         if (!classDefinition.isAspect())
182         {
183             // add nt:base properties
184
defs[i++] = typeManager.getPropertyDefinitionImpl(JCRPrimaryTypeProperty.PROPERTY_NAME);
185             defs[i++] = typeManager.getPropertyDefinitionImpl(JCRMixinTypesProperty.PROPERTY_NAME);
186         }
187         
188         return defs;
189     }
190
191     /* (non-Javadoc)
192      * @see javax.jcr.nodetype.NodeType#getDeclaredPropertyDefinitions()
193      */

194     public PropertyDefinition[] getDeclaredPropertyDefinitions()
195     {
196         Map JavaDoc<QName, org.alfresco.service.cmr.dictionary.PropertyDefinition> propDefs = classDefinition.getProperties();
197         List JavaDoc<PropertyDefinition> defs = new ArrayList JavaDoc<PropertyDefinition>();
198         for (org.alfresco.service.cmr.dictionary.PropertyDefinition propDef : propDefs.values())
199         {
200             if (propDef.getContainerClass().equals(classDefinition))
201             {
202                 defs.add(new PropertyDefinitionImpl(typeManager, propDef));
203             }
204         }
205         
206         if (classDefinition.equals(NT_BASE))
207         {
208             // add nt:base properties
209
defs.add(typeManager.getPropertyDefinitionImpl(JCRPrimaryTypeProperty.PROPERTY_NAME));
210             defs.add(typeManager.getPropertyDefinitionImpl(JCRMixinTypesProperty.PROPERTY_NAME));
211         }
212         
213         return defs.toArray(new PropertyDefinition[defs.size()]);
214     }
215
216     /* (non-Javadoc)
217      * @see javax.jcr.nodetype.NodeType#getChildNodeDefinitions()
218      */

219     public NodeDefinition[] getChildNodeDefinitions()
220     {
221         Map JavaDoc<QName, ChildAssociationDefinition> assocDefs = classDefinition.getChildAssociations();
222         NodeDefinition[] defs = new NodeDefinition[assocDefs.size()];
223         int i = 0;
224         for (ChildAssociationDefinition assocDef : assocDefs.values())
225         {
226             defs[i++] = new NodeDefinitionImpl(typeManager, assocDef);
227         }
228         return defs;
229     }
230
231     /* (non-Javadoc)
232      * @see javax.jcr.nodetype.NodeType#getDeclaredChildNodeDefinitions()
233      */

234     public NodeDefinition[] getDeclaredChildNodeDefinitions()
235     {
236         Map JavaDoc<QName, ChildAssociationDefinition> assocDefs = classDefinition.getChildAssociations();
237         List JavaDoc<NodeDefinition> defs = new ArrayList JavaDoc<NodeDefinition>();
238         for (ChildAssociationDefinition assocDef : assocDefs.values())
239         {
240             if (assocDef.getSourceClass().equals(classDefinition))
241             {
242                 defs.add(new NodeDefinitionImpl(typeManager, assocDef));
243             }
244         }
245         return defs.toArray(new NodeDefinition[defs.size()]);
246     }
247
248     /* (non-Javadoc)
249      * @see javax.jcr.nodetype.NodeType#canSetProperty(java.lang.String, javax.jcr.Value)
250      */

251     public boolean canSetProperty(String JavaDoc propertyName, Value value)
252     {
253         try
254         {
255             // is an attempt to remove property being made
256
if (value == null)
257             {
258                 return canRemoveItem(propertyName);
259             }
260             
261             // retrieve property definition
262
QName propertyQName = QName.createQName(propertyName, typeManager.getNamespaceService());
263             Map JavaDoc<QName, org.alfresco.service.cmr.dictionary.PropertyDefinition> propDefs = classDefinition.getProperties();
264             org.alfresco.service.cmr.dictionary.PropertyDefinition propDef = propDefs.get(propertyQName);
265             if (propDef == null)
266             {
267                 // Alfresco doesn't have residual properties yet
268
return false;
269             }
270             
271             // is property read-write
272
if (propDef.isProtected() || propDef.isMultiValued())
273             {
274                 return false;
275             }
276             
277             // get required type to convert to
278
int requiredType = DataTypeMap.convertDataTypeToPropertyType(propDef.getDataType().getName());
279             if (requiredType == PropertyType.UNDEFINED)
280             {
281                 requiredType = value.getType();
282             }
283
284             // convert value to required type
285
// Note: Invalid conversion will throw exception
286
ValueImpl.getValue(typeManager.getSession().getTypeConverter(), requiredType, value);
287             
288             // Note: conversion succeeded
289
return true;
290         }
291         catch(RepositoryException e)
292         {
293             // Note: Not much can be done really
294
}
295         
296         return false;
297     }
298
299     /* (non-Javadoc)
300      * @see javax.jcr.nodetype.NodeType#canSetProperty(java.lang.String, javax.jcr.Value[])
301      */

302     public boolean canSetProperty(String JavaDoc propertyName, Value[] values)
303     {
304         try
305         {
306             // is an attempt to remove property being made
307
if (values == null)
308             {
309                 return canRemoveItem(propertyName);
310             }
311             
312             // retrieve property definition
313
QName propertyQName = QName.createQName(propertyName, typeManager.getNamespaceService());
314             Map JavaDoc<QName, org.alfresco.service.cmr.dictionary.PropertyDefinition> propDefs = classDefinition.getProperties();
315             org.alfresco.service.cmr.dictionary.PropertyDefinition propDef = propDefs.get(propertyQName);
316             if (propDef == null)
317             {
318                 // Alfresco doesn't have residual properties yet
319
return false;
320             }
321             
322             // is property read write
323
if (propDef.isProtected() || !propDef.isMultiValued())
324             {
325                 return false;
326             }
327
328             // determine type of values to check
329
int valueType = PropertyType.UNDEFINED;
330             for (Value value : values)
331             {
332                 if (value != null)
333                 {
334                     if (valueType != PropertyType.UNDEFINED && value.getType() != valueType)
335                     {
336                         // do not allow collection mixed type values
337
return false;
338                     }
339                     valueType = value.getType();
340                 }
341             }
342             
343             // get required type to convert to
344
int requiredType = DataTypeMap.convertDataTypeToPropertyType(propDef.getDataType().getName());
345             if (requiredType == PropertyType.UNDEFINED)
346             {
347                 requiredType = valueType;
348             }
349
350             // convert values to required format
351
// Note: Invalid conversion will throw exception
352
for (Value value : values)
353             {
354                 if (value != null)
355                 {
356                     ValueImpl.getValue(typeManager.getSession().getTypeConverter(), requiredType, value);
357                 }
358             }
359             
360             // Note: conversion succeeded
361
return true;
362         }
363         catch(RepositoryException e)
364         {
365             // Note: Not much can be done really
366
}
367         
368         return false;
369     }
370
371     /* (non-Javadoc)
372      * @see javax.jcr.nodetype.NodeType#canAddChildNode(java.lang.String)
373      */

374     public boolean canAddChildNode(String JavaDoc childNodeName)
375     {
376         // NOTE: Alfresco does not have default primary type notion
377
return false;
378     }
379
380     /* (non-Javadoc)
381      * @see javax.jcr.nodetype.NodeType#canAddChildNode(java.lang.String, java.lang.String)
382      */

383     public boolean canAddChildNode(String JavaDoc childNodeName, String JavaDoc nodeTypeName)
384     {
385         boolean canAdd = false;
386         Map JavaDoc<QName, ChildAssociationDefinition> assocDefs = classDefinition.getChildAssociations();
387         QName childNodeQName = QName.createQName(childNodeName, typeManager.getNamespaceService());
388         ChildAssociationDefinition assocDef = assocDefs.get(childNodeQName);
389         if (assocDef != null)
390         {
391             QName nodeTypeQName = QName.createQName(nodeTypeName, typeManager.getNamespaceService());
392             DictionaryService dictionaryService = typeManager.getSession().getRepositoryImpl().getServiceRegistry().getDictionaryService();
393             canAdd = dictionaryService.isSubClass(nodeTypeQName, assocDef.getTargetClass().getName());
394         }
395         return canAdd;
396     }
397
398     /* (non-Javadoc)
399      * @see javax.jcr.nodetype.NodeType#canRemoveItem(java.lang.String)
400      */

401     public boolean canRemoveItem(String JavaDoc itemName)
402     {
403         boolean isProtected = false;
404         boolean isMandatory = false;
405         
406         // TODO: Property and Association names can clash? What to do?
407
QName itemQName = QName.createQName(itemName, typeManager.getNamespaceService());
408         Map JavaDoc<QName, org.alfresco.service.cmr.dictionary.PropertyDefinition> propDefs = classDefinition.getProperties();
409         org.alfresco.service.cmr.dictionary.PropertyDefinition propDef = propDefs.get(itemQName);
410         if (propDef != null)
411         {
412             isProtected = propDef.isProtected();
413             isMandatory = propDef.isMandatory();
414         }
415         Map JavaDoc<QName, ChildAssociationDefinition> assocDefs = classDefinition.getChildAssociations();
416         ChildAssociationDefinition assocDef = assocDefs.get(itemQName);
417         if (assocDef != null)
418         {
419             isProtected |= assocDef.isProtected();
420             isMandatory |= assocDef.isTargetMandatory();
421         }
422         
423         return !isProtected && !isMandatory;
424     }
425     
426 }
427
Popular Tags