KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > jcr > item > PropertyImpl


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.item;
18
19 import java.io.InputStream JavaDoc;
20 import java.io.Serializable JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Calendar JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.List JavaDoc;
25
26 import javax.jcr.AccessDeniedException;
27 import javax.jcr.Item;
28 import javax.jcr.ItemNotFoundException;
29 import javax.jcr.ItemVisitor;
30 import javax.jcr.Node;
31 import javax.jcr.Property;
32 import javax.jcr.RepositoryException;
33 import javax.jcr.Value;
34 import javax.jcr.ValueFormatException;
35 import javax.jcr.lock.LockException;
36 import javax.jcr.nodetype.ConstraintViolationException;
37 import javax.jcr.nodetype.PropertyDefinition;
38 import javax.jcr.version.VersionException;
39
40 import org.alfresco.jcr.api.JCRNodeRef;
41 import org.alfresco.jcr.dictionary.DataTypeMap;
42 import org.alfresco.jcr.dictionary.PropertyDefinitionImpl;
43 import org.alfresco.jcr.util.JCRProxyFactory;
44 import org.alfresco.repo.content.MimetypeMap;
45 import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
46 import org.alfresco.service.cmr.dictionary.DictionaryService;
47 import org.alfresco.service.cmr.dictionary.InvalidTypeException;
48 import org.alfresco.service.cmr.repository.ContentReader;
49 import org.alfresco.service.cmr.repository.ContentService;
50 import org.alfresco.service.cmr.repository.ContentWriter;
51 import org.alfresco.service.cmr.repository.NodeService;
52 import org.alfresco.service.cmr.repository.Path;
53 import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
54 import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
55 import org.alfresco.service.namespace.QName;
56
57
58 /**
59  * Alfresco implementation of a Property
60  *
61  * @author David Caruana
62  */

63 public class PropertyImpl extends ItemImpl implements Property
64 {
65
66     private NodeImpl node;
67     private QName name;
68     private Property proxy = null;
69     
70     
71     /**
72      * Constructor
73      *
74      * @param session
75      */

76     public PropertyImpl(NodeImpl node, QName name)
77     {
78         super(node.session);
79         this.node = node;
80         this.name = name;
81     }
82
83     /**
84      * Create proxied JCR Property
85      *
86      * @return property
87      */

88     @Override JavaDoc
89     public Property getProxy()
90     {
91         if (proxy == null)
92         {
93             proxy = (Property)JCRProxyFactory.create(this, Property.class, session);
94         }
95         return proxy;
96     }
97     
98     /* (non-Javadoc)
99      * @see javax.jcr.Item#remove()
100      */

101     public void remove() throws VersionException, LockException, ConstraintViolationException, RepositoryException
102     {
103         setValue((Value)null);
104     }
105     
106     /* (non-Javadoc)
107      * @see javax.jcr.Property#setValue(javax.jcr.Value)
108      */

109     public void setValue(Value value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
110     {
111         setPropertyValue(value, -1);
112     }
113
114     /* (non-Javadoc)
115      * @see javax.jcr.Property#setValue(javax.jcr.Value[])
116      */

117     public void setValue(Value[] values) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
118     {
119         setPropertyValue(values, -1);
120     }
121     
122     /* (non-Javadoc)
123      * @see javax.jcr.Property#setValue(java.lang.String)
124      */

125     public void setValue(String JavaDoc value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
126     {
127         setPropertyValue(value, -1);
128     }
129
130     /* (non-Javadoc)
131      * @see javax.jcr.Property#setValue(java.lang.String[])
132      */

133     public void setValue(String JavaDoc[] values) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
134     {
135         setPropertyValue(values, -1);
136     }
137
138     /* (non-Javadoc)
139      * @see javax.jcr.Property#setValue(java.io.InputStream)
140      */

141     public void setValue(InputStream JavaDoc value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
142     {
143         setPropertyValue(value, -1);
144     }
145
146     /* (non-Javadoc)
147      * @see javax.jcr.Property#setValue(long)
148      */

149     public void setValue(long value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
150     {
151         setPropertyValue(value, -1);
152     }
153
154     /* (non-Javadoc)
155      * @see javax.jcr.Property#setValue(double)
156      */

157     public void setValue(double value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
158     {
159         setPropertyValue(value, -1);
160     }
161
162     /* (non-Javadoc)
163      * @see javax.jcr.Property#setValue(java.util.Calendar)
164      */

165     public void setValue(Calendar JavaDoc value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
166     {
167         setPropertyValue((value == null) ? null : value.getTime(), -1);
168     }
169
170     /* (non-Javadoc)
171      * @see javax.jcr.Property#setValue(boolean)
172      */

173     public void setValue(boolean value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
174     {
175         setPropertyValue(value, -1);
176     }
177
178     /* (non-Javadoc)
179      * @see javax.jcr.Property#setValue(javax.jcr.Node)
180      */

181     public void setValue(Node value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
182     {
183         setPropertyValue((value == null) ? null : JCRNodeRef.getNodeRef(value), -1);
184     }
185     
186     /* (non-Javadoc)
187      * @see javax.jcr.Property#getValue()
188      */

189     public Value getValue() throws ValueFormatException, RepositoryException
190     {
191         checkSingleValued();
192         ValueImpl valueImpl = new ValueImpl(session, getType(), getPropertyValue());
193         // TODO: Could consider returning proxied value implementation (but i don't think is necessary)
194
return valueImpl;
195     }
196
197     /* (non-Javadoc)
198      * @see javax.jcr.Property#getValues()
199      */

200     public Value[] getValues() throws ValueFormatException, RepositoryException
201     {
202         // get values from node property
203
checkMultiValued();
204         Collection JavaDoc values = (Collection JavaDoc)getPropertyValue();
205         int type = getType();
206
207         // construct JCR wrappers
208
List JavaDoc<Value> jcrValues = new ArrayList JavaDoc<Value>(values.size());
209         for (Object JavaDoc value : values)
210         {
211             // Note: In JCR all null values are stripped
212
if (value != null)
213             {
214                 // TODO: Could consider returning proxied value implementation (but i don't think is necessary)
215
jcrValues.add(new ValueImpl(session, type, value));
216             }
217         }
218         
219         return jcrValues.toArray(new Value[jcrValues.size()]);
220     }
221
222     /* (non-Javadoc)
223      * @see javax.jcr.Property#getString()
224      */

225     public String JavaDoc getString() throws ValueFormatException, RepositoryException
226     {
227         checkSingleValued();
228         return session.getTypeConverter().stringValue(getPropertyValue());
229     }
230
231     /* (non-Javadoc)
232      * @see javax.jcr.Property#getStream()
233      */

234     public InputStream JavaDoc getStream() throws ValueFormatException, RepositoryException
235     {
236         checkSingleValued();
237         return session.getTypeConverter().streamValue(getPropertyValue());
238     }
239
240     /* (non-Javadoc)
241      * @see javax.jcr.Property#getLong()
242      */

243     public long getLong() throws ValueFormatException, RepositoryException
244     {
245         checkSingleValued();
246         return session.getTypeConverter().longValue(getPropertyValue());
247     }
248
249     /* (non-Javadoc)
250      * @see javax.jcr.Property#getDouble()
251      */

252     public double getDouble() throws ValueFormatException, RepositoryException
253     {
254         checkSingleValued();
255         return session.getTypeConverter().doubleValue(getPropertyValue());
256     }
257
258     /* (non-Javadoc)
259      * @see javax.jcr.Property#getDate()
260      */

261     public Calendar JavaDoc getDate() throws ValueFormatException, RepositoryException
262     {
263         checkSingleValued();
264         return session.getTypeConverter().dateValue(getPropertyValue());
265     }
266
267     /* (non-Javadoc)
268      * @see javax.jcr.Property#getBoolean()
269      */

270     public boolean getBoolean() throws ValueFormatException, RepositoryException
271     {
272         checkSingleValued();
273         return session.getTypeConverter().booleanValue(getPropertyValue());
274     }
275
276     /* (non-Javadoc)
277      * @see javax.jcr.Property#getNode()
278      */

279     public Node getNode() throws ValueFormatException, RepositoryException
280     {
281         checkSingleValued();
282         return session.getTypeConverter().referenceValue(getPropertyValue()).getProxy();
283     }
284
285     /* (non-Javadoc)
286      * @see javax.jcr.Property#getLength()
287      */

288     public long getLength() throws ValueFormatException, RepositoryException
289     {
290         checkSingleValued();
291         return getPropertyLength(getPropertyValue());
292     }
293
294     /* (non-Javadoc)
295      * @see javax.jcr.Property#getLengths()
296      */

297     public long[] getLengths() throws ValueFormatException, RepositoryException
298     {
299         checkMultiValued();
300         Collection JavaDoc values = (Collection JavaDoc)getPropertyValue();
301         long[] lengths = new long[values.size()];
302         int i = 0;
303         for (Object JavaDoc value : values)
304         {
305             lengths[i++] = getPropertyLength(value);
306         }
307         return lengths;
308     }
309
310     /* (non-Javadoc)
311      * @see javax.jcr.Property#getDefinition()
312      */

313     public PropertyDefinition getDefinition() throws RepositoryException
314     {
315         PropertyDefinitionImpl propDefImpl = new PropertyDefinitionImpl(session.getTypeManager(), getPropertyDefinition());
316         return propDefImpl;
317     }
318
319     /* (non-Javadoc)
320      * @see javax.jcr.Property#getType()
321      */

322     public int getType() throws RepositoryException
323     {
324         // TODO: The type should be based on the property value (in the case of undefined required type)
325
return DataTypeMap.convertDataTypeToPropertyType(getPropertyDefinition().getDataType().getName());
326     }
327
328     /* (non-Javadoc)
329      * @see javax.jcr.Item#getName()
330      */

331     public String JavaDoc getName() throws RepositoryException
332     {
333         return name.toPrefixString(session.getNamespaceResolver());
334     }
335
336     /* (non-Javadoc)
337      * @see javax.jcr.Item#isNode()
338      */

339     public boolean isNode()
340     {
341         return false;
342     }
343
344     /* (non-Javadoc)
345      * @see javax.jcr.Item#getParent()
346      */

347     public Node getParent() throws ItemNotFoundException, AccessDeniedException, RepositoryException
348     {
349         return node.getProxy();
350     }
351
352     /* (non-Javadoc)
353      * @see javax.jcr.Item#getPath()
354      */

355     public String JavaDoc getPath() throws RepositoryException
356     {
357         NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
358         Path path = nodeService.getPath(node.getNodeRef());
359         path.append(new JCRPath.SimpleElement(name));
360         return path.toPrefixString(session.getNamespaceResolver());
361     }
362
363     /* (non-Javadoc)
364      * @see javax.jcr.Item#getDepth()
365      */

366     public int getDepth() throws RepositoryException
367     {
368         NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
369         Path path = nodeService.getPath(node.getNodeRef());
370         // Note: Property is one depth lower than its node
371
return path.size();
372     }
373
374     /* (non-Javadoc)
375      * @see javax.jcr.Item#getAncestor(int)
376      */

377     public Item getAncestor(int depth) throws ItemNotFoundException, AccessDeniedException, RepositoryException
378     {
379         int propertyDepth = getDepth();
380         if (depth < 0 || depth > propertyDepth)
381         {
382             throw new ItemNotFoundException("Ancestor at depth " + depth + " not found for property " + name);
383         }
384
385         if (depth == propertyDepth)
386         {
387             return this.getProxy();
388         }
389         else
390         {
391             return node.getAncestor(depth -1);
392         }
393     }
394
395     /* (non-Javadoc)
396      * @see javax.jcr.Item#isSame(javax.jcr.Item)
397      */

398     public boolean isSame(Item otherItem) throws RepositoryException
399     {
400         return getProxy().equals(otherItem);
401     }
402     
403     /* (non-Javadoc)
404      * @see javax.jcr.Item#accept(javax.jcr.ItemVisitor)
405      */

406     public void accept(ItemVisitor visitor) throws RepositoryException
407     {
408         visitor.visit(getProxy());
409     }
410         
411     /**
412      * Gets the Node Implementation that contains this property
413      *
414      * @return the node implementation
415      */

416     protected NodeImpl getNodeImpl()
417     {
418         return node;
419     }
420
421     /**
422      * Gets the Property Name
423      *
424      * @return the property name
425      */

426     protected QName getPropertyName()
427     {
428         return name;
429     }
430     
431     /**
432      * Gets the property value
433      *
434      * @return the property value
435      */

436     protected Object JavaDoc getPropertyValue()
437         throws RepositoryException
438     {
439         Object JavaDoc value = null;
440
441         if (getPropertyDefinition().getDataType().getName().equals(DataTypeDefinition.CONTENT))
442         {
443             // Retrieve content reader as value
444
ContentService contentService = node.session.getRepositoryImpl().getServiceRegistry().getContentService();
445             value = contentService.getReader(node.getNodeRef(), name);
446             if (value == null)
447             {
448                 // TODO: Check - If value is now null, then effectively the property has been removed
449
throw new RepositoryException("Property " + name + " has been removed.");
450             }
451         }
452         else
453         {
454             // TODO: We may need to copy value here...
455
NodeService nodeService = node.session.getRepositoryImpl().getServiceRegistry().getNodeService();
456             value = nodeService.getProperty(node.getNodeRef(), name);
457             if (value == null)
458             {
459                 // TODO: Check - If value is now null, then effectively the property has been removed
460
throw new RepositoryException("Property " + name + " has been removed.");
461             }
462             
463             // Note: Internal check to ensure that value is single or multi-valued as expected
464
boolean multiValued = getPropertyDefinition().isMultiValued();
465             if (multiValued != (value instanceof Collection JavaDoc))
466             {
467                 throw new RepositoryException("Alfresco value does not match multi-valued definition of " + multiValued);
468             }
469         }
470         
471         return value;
472     }
473
474     /**
475      * Get Length of a Value
476      *
477      * @param value
478      * @return
479      * @throws ValueFormatException
480      * @throws RepositoryException
481      */

482     private long getPropertyLength(Object JavaDoc value) throws ValueFormatException, RepositoryException
483     {
484         // Handle streams
485
if (value instanceof ContentReader)
486         {
487             return ((ContentReader)value).getSize();
488         }
489         if (value instanceof InputStream JavaDoc)
490         {
491             return -1;
492         }
493         
494         // Handle all other data types by converting to string
495
String JavaDoc strValue = (String JavaDoc)DefaultTypeConverter.INSTANCE.convert(String JavaDoc.class, value);
496         return strValue.length();
497     }
498
499     /**
500      * Sets a property value
501      *
502      * @param value the value to set
503      * @param type type to explicitly convert to or -1 to convert to property type
504      * @throws RepositoryException
505      */

506     protected void setPropertyValue(Object JavaDoc value, int type)
507         throws RepositoryException
508     {
509         checkSingleValued();
510         Object JavaDoc castValue = castValue(value, type);
511         writeValue(castValue);
512     }
513     
514     /**
515      * Sets a property value
516      *
517      * @param values the values to set
518      * @param type type to explicitly convert to or -1 to convert to property type
519      * @throws RepositoryException
520      */

521     protected void setPropertyValue(Object JavaDoc[] values, int type)
522         throws RepositoryException
523     {
524         checkMultiValued();
525         
526         // create collection for multi-valued property
527
List JavaDoc<Object JavaDoc> castValues = null;
528         if (values != null)
529         {
530             castValues = new ArrayList JavaDoc<Object JavaDoc>(values.length);
531             for (Object JavaDoc value : values)
532             {
533                 Object JavaDoc castValue = castValue(value, type);
534                 castValues.add(castValue);
535             }
536         }
537         
538         writeValue(castValues);
539     }
540        
541     /**
542      * Cast value to appropriate type for this property
543      *
544      * @param value value to cast
545      * @param type -1 => cast to property type; otherwise cast to type explicitly provided
546      * @return the cast value
547      * @throws RepositoryException
548      */

549     private Object JavaDoc castValue(Object JavaDoc value, int type)
550         throws RepositoryException
551     {
552         // extract raw value if JCR value provided
553
if (value instanceof Value)
554         {
555             value = ValueImpl.getValue((Value)value);
556         }
557
558         // cast value to appropriate type
559
DataTypeDefinition dataTypeDef = getPropertyDefinition().getDataType();
560         if (type != -1 && dataTypeDef.getName().equals(DataTypeDefinition.ANY))
561         {
562             // attempt cast to explicitly specified type, but only in case where property type can be ANY
563
QName dataTypeName = DataTypeMap.convertPropertyTypeToDataType(type);
564             DictionaryService dictionaryService = session.getRepositoryImpl().getServiceRegistry().getDictionaryService();
565             dataTypeDef = dictionaryService.getDataType(dataTypeName);
566             if (!dataTypeName.equals(DataTypeDefinition.CONTENT))
567             {
568                 value = session.getTypeConverter().convert(dataTypeDef, value);
569             }
570         }
571         
572         // special case where binary is converted to inputStream ready for writing via a ContentWriter
573
if (dataTypeDef.getName().equals(DataTypeDefinition.CONTENT))
574         {
575             value = session.getTypeConverter().streamValue(value);
576         }
577         
578         return value;
579     }
580     
581     /**
582      * Write the passed value to the property
583      *
584      * @param value value to write
585      * @throws ValueFormatException
586      */

587     private void writeValue(Object JavaDoc value)
588         throws ValueFormatException
589     {
590         // set the property value
591
if (value instanceof InputStream JavaDoc)
592         {
593             // write content
594
try
595             {
596                 ContentService contentService = session.getRepositoryImpl().getServiceRegistry().getContentService();
597                 ContentWriter writer = contentService.getWriter(node.getNodeRef(), name, true);
598                 writer.setMimetype(MimetypeMap.MIMETYPE_BINARY);
599                 writer.putContent((InputStream JavaDoc)value);
600             }
601             catch(InvalidTypeException e)
602             {
603                 throw new ValueFormatException(e);
604             }
605         }
606         else
607         {
608             // write property value
609
// Note: In the case of Content properties, this effectively "deletes" the content when the value is null
610
try
611             {
612                 NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
613                 nodeService.setProperty(node.getNodeRef(), name, (Serializable JavaDoc)value);
614             }
615             catch(TypeConversionException e)
616             {
617                 throw new ValueFormatException(e);
618             }
619         }
620     }
621     
622     /**
623      * Checks that this property is single valued.
624      *
625      * @throws ValueFormatException if value is multi-valued
626      */

627     private void checkSingleValued()
628         throws ValueFormatException
629     {
630         if (getPropertyDefinition().isMultiValued())
631         {
632             // Expected exception for JSR-170
633
throw new ValueFormatException("Property " + name + " is multi-valued.");
634         }
635     }
636
637     /**
638      * Checks that this property is single valued.
639      *
640      * @throws ValueFormatException if value is multi-valued
641      */

642     private void checkMultiValued()
643         throws ValueFormatException
644     {
645         if (!getPropertyDefinition().isMultiValued())
646         {
647             // Expected exception for JSR-170
648
throw new ValueFormatException("Property " + name + " is single-valued.");
649         }
650     }
651     
652     /**
653      * Gets the Property Data Type
654      *
655      * @return the (JCR) data type
656      */

657     private org.alfresco.service.cmr.dictionary.PropertyDefinition getPropertyDefinition()
658     {
659         DictionaryService dictionary = session.getRepositoryImpl().getServiceRegistry().getDictionaryService();
660         return dictionary.getProperty(name);
661     }
662     
663     @Override JavaDoc
664     public boolean equals(Object JavaDoc obj)
665     {
666         if (obj == this)
667         {
668             return true;
669         }
670         if (!(obj instanceof PropertyImpl))
671         {
672             return false;
673         }
674         PropertyImpl other = (PropertyImpl)obj;
675         return this.name.equals(other.name);
676     }
677
678     @Override JavaDoc
679     public int hashCode()
680     {
681         return name.hashCode();
682     }
683
684 }
685
Popular Tags