This project has retired. For details please refer to its Attic page.
ObjectFactoryImpl xref

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.chemistry.opencmis.client.runtime.repository;
20  
21  import java.io.InputStream;
22  import java.io.Serializable;
23  import java.math.BigDecimal;
24  import java.math.BigInteger;
25  import java.util.ArrayList;
26  import java.util.Collections;
27  import java.util.Date;
28  import java.util.GregorianCalendar;
29  import java.util.HashMap;
30  import java.util.LinkedHashMap;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.Set;
34  
35  import org.apache.chemistry.opencmis.client.api.ChangeEvent;
36  import org.apache.chemistry.opencmis.client.api.ChangeEvents;
37  import org.apache.chemistry.opencmis.client.api.CmisObject;
38  import org.apache.chemistry.opencmis.client.api.ObjectFactory;
39  import org.apache.chemistry.opencmis.client.api.ObjectType;
40  import org.apache.chemistry.opencmis.client.api.OperationContext;
41  import org.apache.chemistry.opencmis.client.api.Policy;
42  import org.apache.chemistry.opencmis.client.api.Property;
43  import org.apache.chemistry.opencmis.client.api.QueryResult;
44  import org.apache.chemistry.opencmis.client.api.Rendition;
45  import org.apache.chemistry.opencmis.client.api.Session;
46  import org.apache.chemistry.opencmis.client.runtime.ChangeEventImpl;
47  import org.apache.chemistry.opencmis.client.runtime.ChangeEventsImpl;
48  import org.apache.chemistry.opencmis.client.runtime.DocumentImpl;
49  import org.apache.chemistry.opencmis.client.runtime.FolderImpl;
50  import org.apache.chemistry.opencmis.client.runtime.PolicyImpl;
51  import org.apache.chemistry.opencmis.client.runtime.PropertyImpl;
52  import org.apache.chemistry.opencmis.client.runtime.QueryResultImpl;
53  import org.apache.chemistry.opencmis.client.runtime.RelationshipImpl;
54  import org.apache.chemistry.opencmis.client.runtime.RenditionImpl;
55  import org.apache.chemistry.opencmis.client.runtime.SessionImpl;
56  import org.apache.chemistry.opencmis.client.runtime.objecttype.DocumentTypeImpl;
57  import org.apache.chemistry.opencmis.client.runtime.objecttype.FolderTypeImpl;
58  import org.apache.chemistry.opencmis.client.runtime.objecttype.PolicyTypeImpl;
59  import org.apache.chemistry.opencmis.client.runtime.objecttype.RelationshipTypeImpl;
60  import org.apache.chemistry.opencmis.commons.PropertyIds;
61  import org.apache.chemistry.opencmis.commons.data.Ace;
62  import org.apache.chemistry.opencmis.commons.data.Acl;
63  import org.apache.chemistry.opencmis.commons.data.ContentStream;
64  import org.apache.chemistry.opencmis.commons.data.ObjectData;
65  import org.apache.chemistry.opencmis.commons.data.ObjectList;
66  import org.apache.chemistry.opencmis.commons.data.Properties;
67  import org.apache.chemistry.opencmis.commons.data.PropertyData;
68  import org.apache.chemistry.opencmis.commons.data.PropertyId;
69  import org.apache.chemistry.opencmis.commons.data.RenditionData;
70  import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
71  import org.apache.chemistry.opencmis.commons.definitions.DocumentTypeDefinition;
72  import org.apache.chemistry.opencmis.commons.definitions.FolderTypeDefinition;
73  import org.apache.chemistry.opencmis.commons.definitions.PolicyTypeDefinition;
74  import org.apache.chemistry.opencmis.commons.definitions.PropertyBooleanDefinition;
75  import org.apache.chemistry.opencmis.commons.definitions.PropertyDateTimeDefinition;
76  import org.apache.chemistry.opencmis.commons.definitions.PropertyDecimalDefinition;
77  import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
78  import org.apache.chemistry.opencmis.commons.definitions.PropertyHtmlDefinition;
79  import org.apache.chemistry.opencmis.commons.definitions.PropertyIdDefinition;
80  import org.apache.chemistry.opencmis.commons.definitions.PropertyIntegerDefinition;
81  import org.apache.chemistry.opencmis.commons.definitions.PropertyStringDefinition;
82  import org.apache.chemistry.opencmis.commons.definitions.PropertyUriDefinition;
83  import org.apache.chemistry.opencmis.commons.definitions.RelationshipTypeDefinition;
84  import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
85  import org.apache.chemistry.opencmis.commons.enums.Cardinality;
86  import org.apache.chemistry.opencmis.commons.enums.ChangeType;
87  import org.apache.chemistry.opencmis.commons.enums.Updatability;
88  import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
89  import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
90  import org.apache.chemistry.opencmis.commons.spi.BindingsObjectFactory;
91  
92  /**
93   * Persistent model object factory.
94   */
95  public class ObjectFactoryImpl implements ObjectFactory, Serializable {
96  
97      private static final long serialVersionUID = 1L;
98  
99      private Session session;
100 
101     /**
102      * Default constructor.
103      */
104     public ObjectFactoryImpl() {
105     }
106 
107     public void initialize(Session session, Map<String, String> parameters) {
108         this.session = session;
109     }
110 
111     /**
112      * Returns the bindings object factory.
113      */
114     protected BindingsObjectFactory getBindingsObjectFactory() {
115         return session.getBinding().getObjectFactory();
116     }
117 
118     // repository info
119 
120     public RepositoryInfo convertRepositoryInfo(RepositoryInfo repositoryInfo) {
121         return repositoryInfo;
122     }
123 
124     // ACL and ACE
125 
126     public Acl convertAces(List<Ace> aces) {
127         if (aces == null) {
128             return null;
129         }
130 
131         BindingsObjectFactory bof = getBindingsObjectFactory();
132 
133         List<Ace> bindingAces = new ArrayList<Ace>();
134         for (Ace ace : aces) {
135             bindingAces.add(bof.createAccessControlEntry(ace.getPrincipalId(), ace.getPermissions()));
136         }
137 
138         return bof.createAccessControlList(bindingAces);
139     }
140 
141     public Ace createAce(String principal, List<String> permissions) {
142         BindingsObjectFactory bof = getBindingsObjectFactory();
143 
144         Ace ace = bof.createAccessControlEntry(principal, permissions);
145 
146         return ace;
147     }
148 
149     public Acl createAcl(List<Ace> aces) {
150         BindingsObjectFactory bof = getBindingsObjectFactory();
151 
152         Acl acl = bof.createAccessControlList(aces);
153 
154         return acl;
155     }
156 
157     // policies
158 
159     public List<String> convertPolicies(List<Policy> policies) {
160         if (policies == null) {
161             return null;
162         }
163 
164         List<String> result = new ArrayList<String>();
165 
166         for (Policy policy : policies) {
167             if ((policy != null) && (policy.getId() != null)) {
168                 result.add(policy.getId());
169             }
170         }
171 
172         return result;
173     }
174 
175     // renditions
176 
177     public Rendition convertRendition(String objectId, RenditionData rendition) {
178         if (rendition == null) {
179             throw new IllegalArgumentException("Rendition must be set!");
180         }
181 
182         long length = (rendition.getBigLength() == null ? -1 : rendition.getBigLength().longValue());
183         int height = (rendition.getBigHeight() == null ? -1 : rendition.getBigHeight().intValue());
184         int width = (rendition.getBigWidth() == null ? -1 : rendition.getBigWidth().intValue());
185 
186         return new RenditionImpl(this.session, objectId, rendition.getStreamId(), rendition.getRenditionDocumentId(),
187                 rendition.getKind(), length, rendition.getMimeType(), rendition.getTitle(), height, width);
188     }
189 
190     // content stream
191 
192     public ContentStream createContentStream(String filename, long length, String mimetype, InputStream stream) {
193         return new ContentStreamImpl(filename, BigInteger.valueOf(length), mimetype, stream);
194     }
195 
196     public ContentStream convertContentStream(ContentStream contentStream) {
197         if (contentStream == null) {
198             return null;
199         }
200 
201         BigInteger length = (contentStream.getLength() < 0 ? null : BigInteger.valueOf(contentStream.getLength()));
202 
203         return getBindingsObjectFactory().createContentStream(contentStream.getFileName(), length,
204                 contentStream.getMimeType(), contentStream.getStream());
205     }
206 
207     // types
208 
209     public ObjectType convertTypeDefinition(TypeDefinition typeDefinition) {
210         if (typeDefinition instanceof DocumentTypeDefinition) {
211             return new DocumentTypeImpl(this.session, (DocumentTypeDefinition) typeDefinition);
212         } else if (typeDefinition instanceof FolderTypeDefinition) {
213             return new FolderTypeImpl(this.session, (FolderTypeDefinition) typeDefinition);
214         } else if (typeDefinition instanceof RelationshipTypeDefinition) {
215             return new RelationshipTypeImpl(this.session, (RelationshipTypeDefinition) typeDefinition);
216         } else if (typeDefinition instanceof PolicyTypeDefinition) {
217             return new PolicyTypeImpl(this.session, (PolicyTypeDefinition) typeDefinition);
218         } else if (typeDefinition == null) {
219             throw new CmisRuntimeException("No base type supplied!");
220         } else {
221             throw new CmisRuntimeException("Unknown base type! Received " + typeDefinition.getClass().getName());
222         }
223     }
224 
225     public ObjectType getTypeFromObjectData(ObjectData objectData) {
226         if ((objectData == null) || (objectData.getProperties() == null)
227                 || (objectData.getProperties().getProperties() == null)) {
228             return null;
229         }
230 
231         PropertyData<?> typeProperty = objectData.getProperties().getProperties().get(PropertyIds.OBJECT_TYPE_ID);
232         if (!(typeProperty instanceof PropertyId)) {
233             return null;
234         }
235 
236         return this.session.getTypeDefinition((String) typeProperty.getFirstValue());
237     }
238 
239     // properties
240 
241     public <T> Property<T> createProperty(PropertyDefinition<T> type, List<T> values) {
242         return new PropertyImpl<T>(type, values);
243     }
244 
245     @SuppressWarnings("unchecked")
246     protected <T> Property<T> convertProperty(ObjectType objectType, PropertyData<T> pd) {
247         PropertyDefinition<T> definition = (PropertyDefinition<T>) objectType.getPropertyDefinitions().get(pd.getId());
248         if (definition == null) {
249             // property without definition
250             throw new CmisRuntimeException("Property '" + pd.getId() + "' doesn't exist!");
251         }
252         return createProperty(definition, pd.getValues());
253     }
254 
255     public Map<String, Property<?>> convertProperties(ObjectType objectType, Properties properties) {
256         // check input
257         if (objectType == null) {
258             throw new IllegalArgumentException("Object type must set!");
259         }
260 
261         if (objectType.getPropertyDefinitions() == null) {
262             throw new IllegalArgumentException("Object type has no property defintions!");
263         }
264 
265         if ((properties == null) || (properties.getProperties() == null)) {
266             throw new IllegalArgumentException("Properties must be set!");
267         }
268 
269         // iterate through properties and convert them
270         Map<String, Property<?>> result = new LinkedHashMap<String, Property<?>>();
271         for (Map.Entry<String, PropertyData<?>> entry : properties.getProperties().entrySet()) {
272             // find property definition
273             Property<?> apiProperty = convertProperty(objectType, entry.getValue());
274             result.put(entry.getKey(), apiProperty);
275         }
276 
277         return result;
278     }
279 
280     @SuppressWarnings("unchecked")
281     public Properties convertProperties(Map<String, ?> properties, ObjectType type, Set<Updatability> updatabilityFilter) {
282         // check input
283         if (properties == null) {
284             return null;
285         }
286 
287         // get the type
288         if (type == null) {
289             Object typeId = properties.get(PropertyIds.OBJECT_TYPE_ID);
290             if (!(typeId instanceof String)) {
291                 throw new IllegalArgumentException("Type or type property must be set!");
292             }
293 
294             type = session.getTypeDefinition(typeId.toString());
295         }
296 
297         // some preparation
298         BindingsObjectFactory bof = getBindingsObjectFactory();
299         List<PropertyData<?>> propertyList = new ArrayList<PropertyData<?>>();
300 
301         // the big loop
302         for (Map.Entry<String, ?> property : properties.entrySet()) {
303             if ((property == null) || (property.getKey() == null)) {
304                 continue;
305             }
306 
307             String id = property.getKey();
308             Object value = property.getValue();
309 
310             if (value instanceof Property<?>) {
311                 Property<?> p = (Property<?>) value;
312                 if (!id.equals(p.getId())) {
313                     throw new IllegalArgumentException("Property id mismatch: '" + id + "' != '" + p.getId() + "'!");
314                 }
315                 value = (p.getDefinition().getCardinality() == Cardinality.SINGLE ? p.getFirstValue() : p.getValues());
316             }
317 
318             // get the property definition
319             PropertyDefinition<?> definition = type.getPropertyDefinitions().get(id);
320             if (definition == null) {
321                 throw new IllegalArgumentException("Property '" + id + "' is not valid for this type!");
322             }
323 
324             // check updatability
325             if (updatabilityFilter != null) {
326                 if (!updatabilityFilter.contains(definition.getUpdatability())) {
327                     continue;
328                 }
329             }
330 
331             // single and multi value check
332             List<?> values;
333             if (value == null) {
334                 values = null;
335             } else if (value instanceof List<?>) {
336                 if (definition.getCardinality() != Cardinality.MULTI) {
337                     throw new IllegalArgumentException("Property '" + id + "' is not a multi value property!");
338                 }
339                 values = (List<?>) value;
340 
341                 // check if the list is homogeneous and does not contain null
342                 // values
343                 Class<?> valueClazz = null;
344                 for (Object o : values) {
345                     if (o == null) {
346                         throw new IllegalArgumentException("Property '" + id + "' contains null values!");
347                     }
348                     if (valueClazz == null) {
349                         valueClazz = o.getClass();
350                     } else {
351                         if (!valueClazz.isInstance(o)) {
352                             throw new IllegalArgumentException("Property '" + id + "' is inhomogeneous!");
353                         }
354                     }
355                 }
356             } else {
357                 if (definition.getCardinality() != Cardinality.SINGLE) {
358                     throw new IllegalArgumentException("Property '" + id + "' is not a single value property!");
359                 }
360                 values = Collections.singletonList(value);
361             }
362 
363             // assemble property
364             PropertyData<?> propertyData = null;
365             Object firstValue = (values == null || values.isEmpty() ? null : values.get(0));
366 
367             if (definition instanceof PropertyStringDefinition) {
368                 if (firstValue == null) {
369                     propertyData = bof.createPropertyStringData(id, (List<String>) null);
370                 } else if (firstValue instanceof String) {
371                     propertyData = bof.createPropertyStringData(id, (List<String>) values);
372                 } else {
373                     throwWrongTypeError(firstValue, "string", String.class, id);
374                 }
375             } else if (definition instanceof PropertyIdDefinition) {
376                 if (firstValue == null) {
377                     propertyData = bof.createPropertyIdData(id, (List<String>) null);
378                 } else if (firstValue instanceof String) {
379                     propertyData = bof.createPropertyIdData(id, (List<String>) values);
380                 } else {
381                     throwWrongTypeError(firstValue, "string", String.class, id);
382                 }
383             } else if (definition instanceof PropertyHtmlDefinition) {
384                 if (firstValue == null) {
385                     propertyData = bof.createPropertyHtmlData(id, (List<String>) values);
386                 } else if (firstValue instanceof String) {
387                     propertyData = bof.createPropertyHtmlData(id, (List<String>) values);
388                 } else {
389                     throwWrongTypeError(firstValue, "html", String.class, id);
390                 }
391             } else if (definition instanceof PropertyUriDefinition) {
392                 if (firstValue == null) {
393                     propertyData = bof.createPropertyUriData(id, (List<String>) null);
394                 } else if (firstValue instanceof String) {
395                     propertyData = bof.createPropertyUriData(id, (List<String>) values);
396                 } else {
397                     throwWrongTypeError(firstValue, "uri", String.class, id);
398                 }
399             } else if (definition instanceof PropertyIntegerDefinition) {
400                 if (firstValue == null) {
401                     propertyData = bof.createPropertyIntegerData(id, (List<BigInteger>) null);
402                 } else if (firstValue instanceof BigInteger) {
403                     propertyData = bof.createPropertyIntegerData(id, (List<BigInteger>) values);
404                 } else if ((firstValue instanceof Byte) || (firstValue instanceof Short)
405                         || (firstValue instanceof Integer) || (firstValue instanceof Long)) {
406                     // we accept all kinds of integers
407                     List<BigInteger> list = new ArrayList<BigInteger>(values.size());
408                     for (Object v : values) {
409                         list.add(BigInteger.valueOf(((Number) v).longValue()));
410                     }
411 
412                     propertyData = bof.createPropertyIntegerData(id, list);
413                 } else {
414                     throwWrongTypeError(firstValue, "integer", BigInteger.class, id);
415                 }
416             } else if (definition instanceof PropertyBooleanDefinition) {
417                 if (firstValue == null) {
418                     propertyData = bof.createPropertyBooleanData(id, (List<Boolean>) null);
419                 } else if (firstValue instanceof Boolean) {
420                     propertyData = bof.createPropertyBooleanData(id, (List<Boolean>) values);
421                 } else {
422                     throwWrongTypeError(firstValue, "boolean", Boolean.class, id);
423                 }
424             } else if (definition instanceof PropertyDecimalDefinition) {
425                 if (firstValue == null) {
426                     propertyData = bof.createPropertyDecimalData(id, (List<BigDecimal>) null);
427                 } else if (firstValue instanceof BigDecimal) {
428                     propertyData = bof.createPropertyDecimalData(id, (List<BigDecimal>) values);
429                 } else if ((firstValue instanceof Float) || (firstValue instanceof Double)
430                         || (firstValue instanceof Byte) || (firstValue instanceof Short)
431                         || (firstValue instanceof Integer) || (firstValue instanceof Long)) {
432                     // we accept all kinds of integers
433                     // as well as floats and doubles
434                     List<BigDecimal> list = new ArrayList<BigDecimal>(values.size());
435                     for (Object v : values) {
436                         list.add(new BigDecimal(v.toString()));
437                     }
438 
439                     propertyData = bof.createPropertyDecimalData(id, list);
440                 } else {
441                     throwWrongTypeError(firstValue, "decimal", BigDecimal.class, id);
442                 }
443             } else if (definition instanceof PropertyDateTimeDefinition) {
444                 if (firstValue == null) {
445                     propertyData = bof.createPropertyDateTimeData(id, (List<GregorianCalendar>) null);
446                 } else if (firstValue instanceof GregorianCalendar) {
447                     propertyData = bof.createPropertyDateTimeData(id, (List<GregorianCalendar>) values);
448                 } else if (firstValue instanceof Date) {
449                     List<GregorianCalendar> list = new ArrayList<GregorianCalendar>(values.size());
450                     for (Object d : values) {
451                         GregorianCalendar cal = new GregorianCalendar();
452                         cal.setTime((Date)d);
453                         list.add(cal);
454                     }
455                     propertyData = bof.createPropertyDateTimeData(id, list);
456                 } else {
457                     throwWrongTypeError(firstValue, "datetime", GregorianCalendar.class, id);
458                 }
459             }
460 
461             // do we have something?
462             if (propertyData == null) {
463                 throw new IllegalArgumentException("Property '" + id + "' doesn't match the property defintion!");
464             }
465 
466             propertyList.add(propertyData);
467         }
468 
469         return bof.createPropertiesData(propertyList);
470     }
471 
472     public List<PropertyData<?>> convertQueryProperties(Properties properties) {
473         // check input
474         if ((properties == null) || (properties.getProperties() == null)) {
475             throw new IllegalArgumentException("Properties must be set!");
476         }
477         return new ArrayList<PropertyData<?>>(properties.getPropertyList());
478     }
479 
480     // objects
481 
482     public CmisObject convertObject(ObjectData objectData, OperationContext context) {
483         if (objectData == null) {
484             throw new IllegalArgumentException("Object data is null!");
485         }
486 
487         ObjectType type = getTypeFromObjectData(objectData);
488 
489         /* determine type */
490         switch (objectData.getBaseTypeId()) {
491         case CMIS_DOCUMENT:
492             return new DocumentImpl((SessionImpl) this.session, type, objectData, context);
493         case CMIS_FOLDER:
494             return new FolderImpl((SessionImpl) this.session, type, objectData, context);
495         case CMIS_POLICY:
496             return new PolicyImpl((SessionImpl) this.session, type, objectData, context);
497         case CMIS_RELATIONSHIP:
498             return new RelationshipImpl((SessionImpl) this.session, type, objectData, context);
499         default:
500             throw new CmisRuntimeException("unsupported type: " + objectData.getBaseTypeId());
501         }
502     }
503 
504     public QueryResult convertQueryResult(ObjectData objectData) {
505         if (objectData == null) {
506             throw new IllegalArgumentException("Object data is null!");
507         }
508 
509         return new QueryResultImpl(session, objectData);
510     }
511 
512     public ChangeEvent convertChangeEvent(ObjectData objectData) {
513         ChangeType changeType = null;
514         GregorianCalendar changeTime = null;
515         String objectId = null;
516         Map<String, List<?>> properties = null;
517         List<String> policyIds = null;
518         Acl acl = null;
519 
520         if (objectData.getChangeEventInfo() != null) {
521             changeType = objectData.getChangeEventInfo().getChangeType();
522             changeTime = objectData.getChangeEventInfo().getChangeTime();
523         }
524 
525         if ((objectData.getProperties() != null) && (objectData.getProperties().getPropertyList() != null)) {
526             properties = new HashMap<String, List<?>>();
527 
528             for (PropertyData<?> property : objectData.getProperties().getPropertyList()) {
529                 properties.put(property.getId(), property.getValues());
530             }
531 
532             if (properties.containsKey(PropertyIds.OBJECT_ID)) {
533                 List<?> objectIdList = properties.get(PropertyIds.OBJECT_ID);
534                 if ((objectIdList != null) && (!objectIdList.isEmpty())) {
535                     objectId = objectIdList.get(0).toString();
536                 }
537             }
538 
539             if ((objectData.getPolicyIds() != null) && (objectData.getPolicyIds().getPolicyIds() != null)) {
540                 policyIds = objectData.getPolicyIds().getPolicyIds();
541             }
542 
543             if (objectData.getAcl() != null) {
544                 acl = objectData.getAcl();
545             }
546         }
547 
548         return new ChangeEventImpl(changeType, changeTime, objectId, properties, policyIds, acl);
549     }
550 
551     public ChangeEvents convertChangeEvents(String changeLogToken, ObjectList objectList) {
552         if (objectList == null) {
553             return null;
554         }
555 
556         List<ChangeEvent> events = new ArrayList<ChangeEvent>();
557         if (objectList.getObjects() != null) {
558             for (ObjectData objectData : objectList.getObjects()) {
559                 if (objectData == null) {
560                     continue;
561                 }
562 
563                 events.add(convertChangeEvent(objectData));
564             }
565         }
566 
567         boolean hasMoreItems = (objectList.hasMoreItems() == null ? false : objectList.hasMoreItems().booleanValue());
568         long totalNumItems = (objectList.getNumItems() == null ? -1 : objectList.getNumItems().longValue());
569 
570         return new ChangeEventsImpl(changeLogToken, events, hasMoreItems, totalNumItems);
571     }
572     
573     private void throwWrongTypeError(Object obj, String type, Class<?> clazz, String id) {
574         String expectedTypes;
575         if (clazz.equals(BigInteger.class))
576             expectedTypes = "<BigInteger, Byte, Short, Integer, Long>";
577         else if (clazz.equals(BigDecimal.class))
578             expectedTypes = "<BigDecimal, Double, Float, Byte, Short, Integer, Long>";
579         else if (clazz.equals(GregorianCalendar.class))
580             expectedTypes = "<java.util.GregorianCalendar, java.util.Date>";
581         else
582             expectedTypes = clazz.getName();
583             
584         String message = "Property '" + id +"' is a " + type + " property. Expected type '"
585                 + expectedTypes + "' but received a '" + obj.getClass().getName() + "' property.";
586         
587         throw new IllegalArgumentException(message);
588     }
589 }
590