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 */
019package org.crsh.jcr;
020
021import javax.jcr.*;
022import java.io.InputStream;
023import java.math.BigDecimal;
024import java.math.BigInteger;
025import java.util.*;
026
027public 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}