001    /*
002     * Copyright (C) 2003-2009 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    /**
028     * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
029     * @version $Revision$
030     */
031    public enum PropertyType {
032    
033      PATH(javax.jcr.PropertyType.PATH){
034        @Override
035        public Object unwrap(Value value) throws RepositoryException {
036          return value.getString();
037        }
038        @Override
039        protected Value wrap(ValueFactory factory, Object value) {
040          if (value instanceof String) {
041            return factory.createValue((String)value);
042          } else {
043            return null;
044          }
045        }
046        @Override
047        protected Collection<Class<?>> getCanonicalTypes() {
048          return Collections.emptySet();
049        }
050      },
051    
052      STRING(javax.jcr.PropertyType.STRING){
053        @Override
054        public Object unwrap(Value value) throws RepositoryException {
055          return value.getString();
056        }
057        @Override
058        protected Value wrap(ValueFactory factory, Object value) {
059          if (value instanceof String) {
060            return factory.createValue((String) value);
061          } else if (value instanceof Character) {
062            return factory.createValue(Character.toString((Character) value));
063          } else {
064            return null;
065          }
066        }
067        @Override
068        protected Collection<Class<?>> getCanonicalTypes() {
069          return Arrays.<Class<?>>asList(String.class,Character.class);
070        }
071      },
072    
073      LONG(javax.jcr.PropertyType.LONG) {
074        @Override
075        public Object unwrap(Value value) throws RepositoryException {
076          return value.getLong();
077        }
078        @Override
079        protected Value wrap(ValueFactory factory, Object value) {
080          if (value instanceof Long) {
081            return factory.createValue((Long) value);
082          } else if (value instanceof Integer) {
083            return factory.createValue((Integer) value);
084          } else if (value instanceof Byte) {
085            return factory.createValue((Byte) value);
086          } else if (value instanceof BigInteger) {
087            BigInteger biValue = (BigInteger)value;
088            return factory.createValue(biValue.longValue());
089          } else {
090            return null;
091          }
092        }
093        @Override
094        protected Collection<Class<?>> getCanonicalTypes() {
095          return Arrays.<Class<?>>asList(Long.class,Integer.class,Byte.class,BigInteger.class);
096        }
097      },
098    
099      DOUBLE(javax.jcr.PropertyType.DOUBLE) {
100        @Override
101        public Object unwrap(Value value) throws RepositoryException {
102          return value.getDouble();
103        }
104        @Override
105        protected Value wrap(ValueFactory factory, Object value) {
106          if (value instanceof Double) {
107            return factory.createValue((Double) value);
108          }  else if (value instanceof Float) {
109            return factory.createValue((Float) value);
110          } else if (value instanceof BigDecimal) {
111            BigDecimal bdValue = (BigDecimal)value;
112            return factory.createValue(bdValue.doubleValue());
113          } else {
114            return null;
115          }
116        }
117        @Override
118        protected Collection<Class<?>> getCanonicalTypes() {
119          return Arrays.<Class<?>>asList(Double.class,Float.class,BigDecimal.class);
120        }
121      },
122    
123      BOOLEAN(javax.jcr.PropertyType.BOOLEAN) {
124        @Override
125        public Object unwrap(Value value) throws RepositoryException {
126          return value.getBoolean();
127        }
128        @Override
129        protected Value wrap(ValueFactory factory, Object value) {
130          if (value instanceof Boolean) {
131            return factory.createValue((Boolean) value);
132          } else {
133            return null;
134          }
135        }
136        @Override
137        protected Collection<Class<?>> getCanonicalTypes() {
138          return Arrays.<Class<?>>asList(Boolean.class);
139        }
140      },
141    
142      DATE(javax.jcr.PropertyType.DATE) {
143        @Override
144        public Object unwrap(Value value) throws RepositoryException {
145          return value.getDate();
146        }
147        @Override
148        protected Value wrap(ValueFactory factory, Object value) {
149          if (value instanceof Calendar) {
150            return factory.createValue((Calendar) value);
151          } else {
152            return null;
153          }
154        }
155        @Override
156        protected Collection<Class<?>> getCanonicalTypes() {
157          return Arrays.<Class<?>>asList(Calendar.class);
158        }
159      },
160    
161      BINARY(javax.jcr.PropertyType.BINARY) {
162        @Override
163        public Object unwrap(Value value) throws RepositoryException {
164          return value.getStream();
165        }
166        @Override
167        protected Value wrap(ValueFactory factory, Object value) {
168          if (value instanceof InputStream) {
169            return factory.createValue((InputStream) value);
170          } else {
171            return null;
172          }
173        }
174        @Override
175        protected Collection<Class<?>> getCanonicalTypes() {
176          return Arrays.<Class<?>>asList(InputStream.class);
177        }
178      },
179    
180      REFERENCE(javax.jcr.PropertyType.REFERENCE) {
181        @Override
182        public Object unwrap(Value value) throws RepositoryException {
183          throw new AssertionError("It should not be called");
184        }
185        @Override
186        protected Value wrap(ValueFactory factory, Object value) throws RepositoryException {
187          if (value instanceof Node) {
188            return factory.createValue((Node)value);
189          } else {
190            return null;
191          }
192        }
193        @Override
194        protected Collection<Class<?>> getCanonicalTypes() {
195          return Arrays.<Class<?>>asList(Node.class);
196        }
197      };
198    
199      /** . */
200      private static final PropertyType[] all = new PropertyType[20]; // 20 should be enough
201    
202      /** . */
203      private static final Map<Class<?>, PropertyType> canonicalMapping = new HashMap<Class<?>, PropertyType>();
204    
205      static  {
206        for (PropertyType type : PropertyType.values())
207        {
208          all[type.value] = type;
209          for (Class<?> canonicalType : type.getCanonicalTypes())
210          {
211            canonicalMapping.put(canonicalType, type);
212          }
213        }
214      }
215    
216      public static PropertyType fromCanonicalType(Class<?> canonicalType)
217      {
218        for (Class<?> currentType = canonicalType;currentType != null;currentType = currentType.getSuperclass()) {
219          PropertyType type = canonicalMapping.get(currentType);
220          if (type != null) {
221            return type;
222          }
223        }
224    
225        //
226        return null;
227      }
228    
229      public static PropertyType fromValue(int v)
230      {
231        PropertyType type = null;
232        if (v >= 0 && v < all.length)
233        {
234          type = all[v];
235        }
236    
237        //
238        if (type == null)
239        {
240          throw new IllegalArgumentException("JCR Property type " + v + " not handled yet");
241        }
242        else
243        {
244          return type;
245        }
246      }
247    
248      /** . */
249      private final int value;
250    
251      PropertyType(int value) {
252        this.value = value;
253      }
254    
255      public int getValue() {
256        return value;
257      }
258    
259      public Object get(Property property) throws RepositoryException {
260        if (this == REFERENCE) {
261          return property.getNode();
262        } else {
263          Value value;
264          if (property.getDefinition().isMultiple()) {
265            Value[] values = property.getValues();
266            value = values.length > 0 ? values[0] : null;
267          } else {
268            value = property.getValue();
269          }
270          return value != null ? unwrap(value) : null;
271        }
272      }
273    
274      public final Property set(Node node, String name, Object value) throws RepositoryException {
275        Value v = wrap(node.getSession().getValueFactory(), value);
276        if (v != null) {
277          try {
278            return node.setProperty(name, v);
279          } catch (ValueFormatException e) {
280            return node.setProperty(name, new Value[]{v});
281          }
282        }
283        return null;
284      }
285    
286      protected abstract Object unwrap(Value value) throws RepositoryException;
287    
288      protected abstract Value wrap(ValueFactory factory, Object value) throws RepositoryException;
289    
290      protected abstract Collection<Class<?>> getCanonicalTypes();
291    }