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.io.InputStream;
27  import java.util.Calendar;
28  import java.util.UUID;
29  import javax.jcr.Node;
30  import javax.jcr.Property;
31  import javax.jcr.PropertyType;
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.version.VersionException;
38  import net.jcip.annotations.NotThreadSafe;
39  import org.modeshape.graph.Location;
40  import org.modeshape.graph.property.Binary;
41  import org.modeshape.graph.property.Name;
42  import org.modeshape.graph.property.Reference;
43  import org.modeshape.graph.property.ValueFactories;
44  
45  /**
46   * ModeShape implementation of a {@link Property JCR Property} with a single value.
47   * 
48   * @see JcrMultiValueProperty
49   */
50  @NotThreadSafe
51  final class JcrSingleValueProperty extends AbstractJcrProperty {
52  
53      JcrSingleValueProperty( SessionCache cache,
54                              AbstractJcrNode node,
55                              Name name ) {
56          super(cache, node, name);
57      }
58  
59      /**
60       * {@inheritDoc}
61       * 
62       * @see org.modeshape.jcr.AbstractJcrProperty#isMultiple()
63       */
64      @Override
65      boolean isMultiple() {
66          return false;
67      }
68  
69      /**
70       * {@inheritDoc}
71       * 
72       * @see javax.jcr.Property#getBoolean()
73       */
74      public boolean getBoolean() throws RepositoryException {
75          try {
76              return context().getValueFactories().getBooleanFactory().create(property().getFirstValue());
77          } catch (org.modeshape.graph.property.ValueFormatException e) {
78              throw new ValueFormatException(e.getMessage(), e);
79          }
80      }
81  
82      /**
83       * {@inheritDoc}
84       * 
85       * @see javax.jcr.Property#getDate()
86       */
87      public Calendar getDate() throws RepositoryException {
88          try {
89              return context().getValueFactories().getDateFactory().create(property().getFirstValue()).toCalendar();
90          } catch (org.modeshape.graph.property.ValueFormatException e) {
91              throw new ValueFormatException(e.getMessage(), e);
92          }
93      }
94  
95      /**
96       * {@inheritDoc}
97       * 
98       * @see javax.jcr.Property#getDouble()
99       */
100     public double getDouble() throws RepositoryException {
101         try {
102             return context().getValueFactories().getDoubleFactory().create(property().getFirstValue());
103         } catch (org.modeshape.graph.property.ValueFormatException e) {
104             throw new ValueFormatException(e.getMessage(), e);
105         }
106     }
107 
108     /**
109      * {@inheritDoc}
110      * 
111      * @see javax.jcr.Property#getLength()
112      */
113     public long getLength() throws RepositoryException {
114         return createValue(property().getFirstValue()).getLength();
115     }
116 
117     /**
118      * {@inheritDoc}
119      * 
120      * @throws ValueFormatException always
121      * @see javax.jcr.Property#getLengths()
122      */
123     public long[] getLengths() throws ValueFormatException {
124         throw new ValueFormatException(JcrI18n.invalidMethodForSingleValuedProperty.text());
125     }
126 
127     /**
128      * {@inheritDoc}
129      * 
130      * @see javax.jcr.Property#getLong()
131      */
132     public long getLong() throws RepositoryException {
133         try {
134             return context().getValueFactories().getLongFactory().create(property().getFirstValue());
135         } catch (org.modeshape.graph.property.ValueFormatException e) {
136             throw new ValueFormatException(e.getMessage(), e);
137         }
138     }
139 
140     /**
141      * {@inheritDoc}
142      * 
143      * @see javax.jcr.Property#getNode()
144      */
145     public final Node getNode() throws RepositoryException {
146         try {
147             ValueFactories factories = context().getValueFactories();
148             Reference dnaReference = factories.getReferenceFactory().create(property().getFirstValue());
149             UUID uuid = factories.getUuidFactory().create(dnaReference);
150             return cache.findJcrNode(Location.create(uuid));
151         } catch (org.modeshape.graph.property.ValueFormatException e) {
152             throw new ValueFormatException(e.getMessage(), e);
153         }
154     }
155 
156     /**
157      * {@inheritDoc}
158      * 
159      * @see javax.jcr.Property#getStream()
160      */
161     public InputStream getStream() throws RepositoryException {
162         try {
163             Binary binary = context().getValueFactories().getBinaryFactory().create(property().getFirstValue());
164             return new SelfClosingInputStream(binary);
165         } catch (org.modeshape.graph.property.ValueFormatException e) {
166             throw new ValueFormatException(e.getMessage(), e);
167         }
168     }
169 
170     /**
171      * {@inheritDoc}
172      * 
173      * @see javax.jcr.Property#getString()
174      */
175     public String getString() throws RepositoryException {
176         try {
177             return context().getValueFactories().getStringFactory().create(property().getFirstValue());
178         } catch (org.modeshape.graph.property.ValueFormatException e) {
179             throw new ValueFormatException(e.getMessage(), e);
180         }
181     }
182 
183     /**
184      * {@inheritDoc}
185      * 
186      * @see javax.jcr.Property#getValue()
187      */
188     public Value getValue() throws RepositoryException {
189         return createValue(property().getFirstValue());
190     }
191 
192     /**
193      * {@inheritDoc}
194      * 
195      * @see javax.jcr.Property#setValue(javax.jcr.Value)
196      */
197     public void setValue( Value value )
198         throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
199         JcrValue jcrValue = null;
200         checkForLock();
201         
202         if (value instanceof JcrValue) {
203             jcrValue = (JcrValue)value;
204 
205             // Force a conversion as per SetValueValueFormatExceptionTest in JR TCK
206             jcrValue.asType(this.getType());
207 
208             editor().setProperty(name(), jcrValue);
209             return;
210         }
211         if (value == null) {
212             // Then we're to delete the property ...
213             editor().removeProperty(name());
214             return;
215         }
216 
217         // We have to convert from one Value implementation to ours ...
218         switch (value.getType()) {
219             case PropertyType.STRING:
220                 setValue(value.getString());
221                 break;
222             case PropertyType.BINARY:
223                 setValue(value.getStream());
224                 break;
225             case PropertyType.BOOLEAN:
226                 setValue(value.getBoolean());
227                 break;
228             case PropertyType.DATE:
229                 setValue(value.getDate());
230                 break;
231             case PropertyType.DOUBLE:
232                 setValue(value.getDouble());
233                 break;
234             case PropertyType.LONG:
235                 setValue(value.getLong());
236                 break;
237             case PropertyType.NAME:
238                 setValue(value.getString());
239                 break;
240             case PropertyType.PATH:
241                 setValue(value.getString());
242                 break;
243             case PropertyType.REFERENCE:
244                 setValue(value.getString());
245                 break;
246             default:
247                 throw new RepositoryException(JcrI18n.invalidPropertyType.text(value.getType()));
248         }
249     }
250 
251     protected void setValue( JcrValue jcrValue )
252         throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
253         assert jcrValue != null;
254         
255         checkForLock();
256         
257         editor().setProperty(name(), jcrValue);
258     }
259 
260     /**
261      * {@inheritDoc}
262      * 
263      * @see javax.jcr.Property#setValue(java.lang.String)
264      */
265     public void setValue( String value )
266         throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
267         if (value == null) {
268             this.remove();
269             return;
270         }
271         setValue(createValue(value, PropertyType.STRING).asType(this.getType()));
272     }
273 
274     /**
275      * {@inheritDoc}
276      * 
277      * @see javax.jcr.Property#setValue(java.io.InputStream)
278      */
279     public void setValue( InputStream value )
280         throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
281         if (value == null) {
282             this.remove();
283             return;
284         }
285         setValue(createValue(context().getValueFactories().getBinaryFactory().create(value), PropertyType.BINARY).asType(this.getType()));
286     }
287 
288     /**
289      * {@inheritDoc}
290      * 
291      * @see javax.jcr.Property#setValue(long)
292      */
293     public void setValue( long value )
294         throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
295         setValue(createValue(new Long(value), PropertyType.LONG).asType(this.getType()));
296     }
297 
298     /**
299      * {@inheritDoc}
300      * 
301      * @see javax.jcr.Property#setValue(double)
302      */
303     public void setValue( double value )
304         throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
305         setValue(createValue(new Double(value), PropertyType.DOUBLE).asType(this.getType()));
306     }
307 
308     /**
309      * {@inheritDoc}
310      * 
311      * @see javax.jcr.Property#setValue(java.util.Calendar)
312      */
313     public void setValue( Calendar value )
314         throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
315         if (value == null) {
316             this.remove();
317             return;
318         }
319         setValue(createValue(context().getValueFactories().getDateFactory().create(value), PropertyType.DATE).asType(this.getType()));
320     }
321 
322     /**
323      * {@inheritDoc}
324      * 
325      * @see javax.jcr.Property#setValue(boolean)
326      */
327     public void setValue( boolean value )
328         throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
329         setValue(createValue(new Boolean(value), PropertyType.BOOLEAN).asType(this.getType()));
330     }
331 
332     /**
333      * {@inheritDoc}
334      * 
335      * @see javax.jcr.Property#setValue(javax.jcr.Node)
336      */
337     public void setValue( Node value )
338         throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
339         if (value == null) {
340             this.remove();
341             return;
342         }
343 
344         if (!value.isNodeType(JcrMixLexicon.REFERENCEABLE.getString(this.context().getNamespaceRegistry()))) {
345             throw new ValueFormatException(JcrI18n.nodeNotReferenceable.text());
346         }
347 
348         String uuid = value.getUUID();
349         setValue(createValue(uuid, PropertyType.REFERENCE).asType(this.getType()));
350     }
351 
352     /**
353      * {@inheritDoc}
354      * 
355      * @throws ValueFormatException always
356      * @see javax.jcr.Property#getValues()
357      */
358     public Value[] getValues() throws ValueFormatException {
359         throw new ValueFormatException(JcrI18n.invalidMethodForSingleValuedProperty.text());
360     }
361 
362     /**
363      * {@inheritDoc}
364      * 
365      * @see javax.jcr.Property#setValue(javax.jcr.Value[])
366      */
367     public void setValue( Value[] values ) throws ValueFormatException {
368         throw new ValueFormatException(JcrI18n.invalidMethodForSingleValuedProperty.text());
369     }
370 
371     /**
372      * {@inheritDoc}
373      * 
374      * @see javax.jcr.Property#setValue(java.lang.String[])
375      */
376     public void setValue( String[] values ) throws ValueFormatException {
377         throw new ValueFormatException(JcrI18n.invalidMethodForSingleValuedProperty.text());
378     }
379 }