001    /*
002     * Copyright (C) 2012 eXo Platform SAS.
003     *
004     * This is free software; you can redistribute it and/or modify it
005     * under the terms of the GNU Lesser General Public License as
006     * published by the Free Software Foundation; either version 2.1 of
007     * the License, or (at your option) any later version.
008     *
009     * This software is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this software; if not, write to the Free
016     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018     */
019    package org.crsh.jcr;
020    
021    import javax.jcr.*;
022    import java.io.InputStream;
023    import java.math.BigDecimal;
024    import java.math.BigInteger;
025    import java.util.*;
026    
027    public enum PropertyType {
028    
029      PATH(javax.jcr.PropertyType.PATH){
030        @Override
031        public Object unwrap(Value value) throws RepositoryException {
032          return value.getString();
033        }
034        @Override
035        protected Value wrap(ValueFactory factory, Object value) {
036          if (value instanceof String) {
037            return factory.createValue((String)value);
038          } else {
039            return null;
040          }
041        }
042        @Override
043        protected Collection<Class<?>> getCanonicalTypes() {
044          return Collections.emptySet();
045        }
046      },
047    
048      STRING(javax.jcr.PropertyType.STRING){
049        @Override
050        public Object unwrap(Value value) throws RepositoryException {
051          return value.getString();
052        }
053        @Override
054        protected Value wrap(ValueFactory factory, Object value) {
055          if (value instanceof String) {
056            return factory.createValue((String) value);
057          } else if (value instanceof Character) {
058            return factory.createValue(Character.toString((Character) value));
059          } else {
060            return null;
061          }
062        }
063        @Override
064        protected Collection<Class<?>> getCanonicalTypes() {
065          return Arrays.<Class<?>>asList(String.class,Character.class);
066        }
067      },
068    
069      LONG(javax.jcr.PropertyType.LONG) {
070        @Override
071        public Object unwrap(Value value) throws RepositoryException {
072          return value.getLong();
073        }
074        @Override
075        protected Value wrap(ValueFactory factory, Object value) {
076          if (value instanceof Long) {
077            return factory.createValue((Long) value);
078          } else if (value instanceof Integer) {
079            return factory.createValue((Integer) value);
080          } else if (value instanceof Byte) {
081            return factory.createValue((Byte) value);
082          } else if (value instanceof BigInteger) {
083            BigInteger biValue = (BigInteger)value;
084            return factory.createValue(biValue.longValue());
085          } else {
086            return null;
087          }
088        }
089        @Override
090        protected Collection<Class<?>> getCanonicalTypes() {
091          return Arrays.<Class<?>>asList(Long.class,Integer.class,Byte.class,BigInteger.class);
092        }
093      },
094    
095      DOUBLE(javax.jcr.PropertyType.DOUBLE) {
096        @Override
097        public Object unwrap(Value value) throws RepositoryException {
098          return value.getDouble();
099        }
100        @Override
101        protected Value wrap(ValueFactory factory, Object value) {
102          if (value instanceof Double) {
103            return factory.createValue((Double) value);
104          }  else if (value instanceof Float) {
105            return factory.createValue((Float) value);
106          } else if (value instanceof BigDecimal) {
107            BigDecimal bdValue = (BigDecimal)value;
108            return factory.createValue(bdValue.doubleValue());
109          } else {
110            return null;
111          }
112        }
113        @Override
114        protected Collection<Class<?>> getCanonicalTypes() {
115          return Arrays.<Class<?>>asList(Double.class,Float.class,BigDecimal.class);
116        }
117      },
118    
119      BOOLEAN(javax.jcr.PropertyType.BOOLEAN) {
120        @Override
121        public Object unwrap(Value value) throws RepositoryException {
122          return value.getBoolean();
123        }
124        @Override
125        protected Value wrap(ValueFactory factory, Object value) {
126          if (value instanceof Boolean) {
127            return factory.createValue((Boolean) value);
128          } else {
129            return null;
130          }
131        }
132        @Override
133        protected Collection<Class<?>> getCanonicalTypes() {
134          return Arrays.<Class<?>>asList(Boolean.class);
135        }
136      },
137    
138      DATE(javax.jcr.PropertyType.DATE) {
139        @Override
140        public Object unwrap(Value value) throws RepositoryException {
141          return value.getDate();
142        }
143        @Override
144        protected Value wrap(ValueFactory factory, Object value) {
145          if (value instanceof Calendar) {
146            return factory.createValue((Calendar) value);
147          } else {
148            return null;
149          }
150        }
151        @Override
152        protected Collection<Class<?>> getCanonicalTypes() {
153          return Arrays.<Class<?>>asList(Calendar.class);
154        }
155      },
156    
157      BINARY(javax.jcr.PropertyType.BINARY) {
158        @Override
159        public Object unwrap(Value value) throws RepositoryException {
160          return value.getStream();
161        }
162        @Override
163        protected Value wrap(ValueFactory factory, Object value) {
164          if (value instanceof InputStream) {
165            return factory.createValue((InputStream) value);
166          } else {
167            return null;
168          }
169        }
170        @Override
171        protected Collection<Class<?>> getCanonicalTypes() {
172          return Arrays.<Class<?>>asList(InputStream.class);
173        }
174      },
175    
176      REFERENCE(javax.jcr.PropertyType.REFERENCE) {
177        @Override
178        public Object unwrap(Value value) throws RepositoryException {
179          throw new AssertionError("It should not be called");
180        }
181        @Override
182        protected Value wrap(ValueFactory factory, Object value) throws RepositoryException {
183          if (value instanceof Node) {
184            return factory.createValue((Node)value);
185          } else {
186            return null;
187          }
188        }
189        @Override
190        protected Collection<Class<?>> getCanonicalTypes() {
191          return Arrays.<Class<?>>asList(Node.class);
192        }
193      };
194    
195      /** . */
196      private static final PropertyType[] all = new PropertyType[20]; // 20 should be enough
197    
198      /** . */
199      private static final Map<Class<?>, PropertyType> canonicalMapping = new HashMap<Class<?>, PropertyType>();
200    
201      static  {
202        for (PropertyType type : PropertyType.values())
203        {
204          all[type.value] = type;
205          for (Class<?> canonicalType : type.getCanonicalTypes())
206          {
207            canonicalMapping.put(canonicalType, type);
208          }
209        }
210      }
211    
212      public static PropertyType fromCanonicalType(Class<?> canonicalType)
213      {
214        for (Class<?> currentType = canonicalType;currentType != null;currentType = currentType.getSuperclass()) {
215          PropertyType type = canonicalMapping.get(currentType);
216          if (type != null) {
217            return type;
218          }
219        }
220    
221        //
222        return null;
223      }
224    
225      public static PropertyType fromValue(int v)
226      {
227        PropertyType type = null;
228        if (v >= 0 && v < all.length)
229        {
230          type = all[v];
231        }
232    
233        //
234        if (type == null)
235        {
236          throw new IllegalArgumentException("JCR Property type " + v + " not handled yet");
237        }
238        else
239        {
240          return type;
241        }
242      }
243    
244      /** . */
245      private final int value;
246    
247      PropertyType(int value) {
248        this.value = value;
249      }
250    
251      public int getValue() {
252        return value;
253      }
254    
255      public Object get(Property property) throws RepositoryException {
256        if (this == REFERENCE) {
257          return property.getNode();
258        } else {
259          Value value;
260          if (property.getDefinition().isMultiple()) {
261            Value[] values = property.getValues();
262            value = values.length > 0 ? values[0] : null;
263          } else {
264            value = property.getValue();
265          }
266          return value != null ? unwrap(value) : null;
267        }
268      }
269    
270      public final Property set(Node node, String name, Object value) throws RepositoryException {
271        Value v = wrap(node.getSession().getValueFactory(), value);
272        if (v != null) {
273          try {
274            return node.setProperty(name, v);
275          } catch (ValueFormatException e) {
276            return node.setProperty(name, new Value[]{v});
277          }
278        }
279        return null;
280      }
281    
282      protected abstract Object unwrap(Value value) throws RepositoryException;
283    
284      protected abstract Value wrap(ValueFactory factory, Object value) throws RepositoryException;
285    
286      protected abstract Collection<Class<?>> getCanonicalTypes();
287    }