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 }