001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.ecm.core.opencmis.impl.client; 020 021import java.io.InputStream; 022import java.math.BigDecimal; 023import java.math.BigInteger; 024import java.util.ArrayList; 025import java.util.Collection; 026import java.util.Collections; 027import java.util.GregorianCalendar; 028import java.util.List; 029import java.util.Map; 030import java.util.Map.Entry; 031import java.util.Set; 032 033import org.apache.chemistry.opencmis.client.api.ChangeEvent; 034import org.apache.chemistry.opencmis.client.api.ChangeEvents; 035import org.apache.chemistry.opencmis.client.api.ObjectFactory; 036import org.apache.chemistry.opencmis.client.api.ObjectType; 037import org.apache.chemistry.opencmis.client.api.OperationContext; 038import org.apache.chemistry.opencmis.client.api.Policy; 039import org.apache.chemistry.opencmis.client.api.Property; 040import org.apache.chemistry.opencmis.client.api.QueryResult; 041import org.apache.chemistry.opencmis.client.api.Rendition; 042import org.apache.chemistry.opencmis.client.api.SecondaryType; 043import org.apache.chemistry.opencmis.client.api.Session; 044import org.apache.chemistry.opencmis.client.runtime.PropertyImpl; 045import org.apache.chemistry.opencmis.client.runtime.RenditionImpl; 046import org.apache.chemistry.opencmis.client.runtime.objecttype.DocumentTypeImpl; 047import org.apache.chemistry.opencmis.client.runtime.objecttype.FolderTypeImpl; 048import org.apache.chemistry.opencmis.client.runtime.objecttype.PolicyTypeImpl; 049import org.apache.chemistry.opencmis.client.runtime.objecttype.RelationshipTypeImpl; 050import org.apache.chemistry.opencmis.client.runtime.objecttype.SecondaryTypeImpl; 051import org.apache.chemistry.opencmis.commons.PropertyIds; 052import org.apache.chemistry.opencmis.commons.data.Ace; 053import org.apache.chemistry.opencmis.commons.data.Acl; 054import org.apache.chemistry.opencmis.commons.data.ContentStream; 055import org.apache.chemistry.opencmis.commons.data.ObjectData; 056import org.apache.chemistry.opencmis.commons.data.ObjectList; 057import org.apache.chemistry.opencmis.commons.data.Properties; 058import org.apache.chemistry.opencmis.commons.data.PropertyData; 059import org.apache.chemistry.opencmis.commons.data.PropertyId; 060import org.apache.chemistry.opencmis.commons.data.RenditionData; 061import org.apache.chemistry.opencmis.commons.data.RepositoryInfo; 062import org.apache.chemistry.opencmis.commons.definitions.DocumentTypeDefinition; 063import org.apache.chemistry.opencmis.commons.definitions.FolderTypeDefinition; 064import org.apache.chemistry.opencmis.commons.definitions.PolicyTypeDefinition; 065import org.apache.chemistry.opencmis.commons.definitions.PropertyBooleanDefinition; 066import org.apache.chemistry.opencmis.commons.definitions.PropertyDateTimeDefinition; 067import org.apache.chemistry.opencmis.commons.definitions.PropertyDecimalDefinition; 068import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition; 069import org.apache.chemistry.opencmis.commons.definitions.PropertyHtmlDefinition; 070import org.apache.chemistry.opencmis.commons.definitions.PropertyIdDefinition; 071import org.apache.chemistry.opencmis.commons.definitions.PropertyIntegerDefinition; 072import org.apache.chemistry.opencmis.commons.definitions.PropertyStringDefinition; 073import org.apache.chemistry.opencmis.commons.definitions.PropertyUriDefinition; 074import org.apache.chemistry.opencmis.commons.definitions.RelationshipTypeDefinition; 075import org.apache.chemistry.opencmis.commons.definitions.SecondaryTypeDefinition; 076import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition; 077import org.apache.chemistry.opencmis.commons.enums.Cardinality; 078import org.apache.chemistry.opencmis.commons.enums.Updatability; 079import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException; 080import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlListImpl; 081import org.apache.chemistry.opencmis.commons.impl.dataobjects.BindingsObjectFactoryImpl; 082import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl; 083import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl; 084import org.apache.chemistry.opencmis.commons.spi.BindingsObjectFactory; 085import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoObjectData; 086 087/** 088 * Factory for {@link NuxeoObject} and its related classes. 089 */ 090public class NuxeoObjectFactory implements ObjectFactory { 091 092 private final NuxeoSession session; 093 094 private static final BindingsObjectFactory of = new BindingsObjectFactoryImpl(); 095 096 public NuxeoObjectFactory(NuxeoSession session) { 097 this.session = session; 098 } 099 100 @Override 101 public void initialize(Session session, Map<String, String> parameters) { 102 // TODO 103 throw new UnsupportedOperationException(); 104 } 105 106 @Override 107 public RepositoryInfo convertRepositoryInfo(RepositoryInfo repositoryInfo) { 108 return repositoryInfo; 109 } 110 111 @Override 112 public NuxeoObject convertObject(ObjectData data, OperationContext context) { 113 if (data == null || data.getProperties() == null || data.getProperties().getProperties() == null) { 114 return null; 115 } 116 // object type 117 PropertyData<?> propData = data.getProperties().getProperties().get(PropertyIds.OBJECT_TYPE_ID); 118 ObjectType type = session.getTypeDefinition((String) propData.getFirstValue()); 119 // secondary types 120 propData = data.getProperties().getProperties().get(PropertyIds.SECONDARY_OBJECT_TYPE_IDS); 121 List<SecondaryType> secondaryTypes; 122 if (propData == null) { 123 secondaryTypes = Collections.emptyList(); 124 } else { 125 @SuppressWarnings("unchecked") 126 List<String> sts = (List<String>) propData.getValues(); 127 secondaryTypes = new ArrayList<SecondaryType>(sts.size()); 128 for (String st : sts) { 129 secondaryTypes.add((SecondaryType) session.getTypeDefinition(st)); 130 } 131 } 132 return NuxeoObject.construct(session, (NuxeoObjectData) data, type, secondaryTypes); 133 } 134 135 @Override 136 public ObjectType getTypeFromObjectData(ObjectData objectData) { 137 // TODO Auto-generated method stub 138 throw new UnsupportedOperationException(); 139 } 140 141 @Override 142 public Ace createAce(String principal, List<String> permissions) { 143 // TODO Auto-generated method stub 144 throw new UnsupportedOperationException(); 145 } 146 147 @Override 148 public Acl createAcl(List<Ace> aces) { 149 // TODO Auto-generated method stub 150 throw new UnsupportedOperationException(); 151 } 152 153 @Override 154 public <T> Property<T> createProperty(PropertyDefinition<T> type, List<T> values) { 155 return new PropertyImpl<T>(type, values); 156 } 157 158 @Override 159 public ContentStream createContentStream(String filename, long length, String mimetype, InputStream stream) { 160 return new ContentStreamImpl(filename, BigInteger.valueOf(length), mimetype, stream); 161 } 162 163 @Override 164 public ContentStream createContentStream(String filename, long length, String mimetype, InputStream stream, 165 boolean partial) { 166 // TODO partial 167 return createContentStream(filename, length, mimetype, stream); 168 } 169 170 @Override 171 public Acl convertAces(List<Ace> aces) { 172 return aces == null ? null : new AccessControlListImpl(aces); 173 } 174 175 @Override 176 public ContentStream convertContentStream(ContentStream contentStream) { 177 if (contentStream == null) { 178 return null; 179 } 180 long len = contentStream.getLength(); 181 BigInteger length = len < 0 ? null : BigInteger.valueOf(len); 182 return of.createContentStream(contentStream.getFileName(), length, contentStream.getMimeType(), 183 contentStream.getStream()); 184 } 185 186 @Override 187 public List<String> convertPolicies(List<Policy> policies) { 188 if (policies == null) { 189 return null; 190 } 191 List<String> policyIds = new ArrayList<String>(policies.size()); 192 for (Policy p : policies) { 193 policyIds.add(p.getId()); 194 } 195 return policyIds; 196 } 197 198 @Override 199 public Map<String, Property<?>> convertProperties(ObjectType objectType, Collection<SecondaryType> secondaryTypes, 200 Properties properties) { 201 throw new UnsupportedOperationException(); 202 } 203 204 @Override 205 public Properties convertProperties(Map<String, ?> properties, ObjectType type, 206 Collection<SecondaryType> secondaryTypes, Set<Updatability> updatabilityFilter) { 207 if (properties == null) { 208 return null; 209 } 210 // TODO secondaryTypes 211 // TODO updatabilityFilter 212 PropertiesImpl props = new PropertiesImpl(); 213 for (Entry<String, ?> es : properties.entrySet()) { 214 PropertyData<?> prop = convertProperty(es.getKey(), es.getValue(), type); 215 props.addProperty(prop); 216 } 217 return props; 218 } 219 220 @SuppressWarnings("unchecked") 221 protected static PropertyData<?> convertProperty(String key, Object value, ObjectType type) { 222 PropertyDefinition<?> pd = type.getPropertyDefinitions().get(key); 223 if (pd == null) { 224 throw new IllegalArgumentException("Unknown property '" + key + "' for type: " + type.getId()); 225 } 226 boolean single = pd.getCardinality() == Cardinality.SINGLE; 227 228 List<?> values; 229 if (value == null) { 230 values = null; 231 } else if (value instanceof List<?>) { 232 if (single) { 233 throw new IllegalArgumentException("Property '" + key + "' is not a multi value property!"); 234 } 235 values = (List<?>) value; 236 } else { 237 if (!single) { 238 throw new IllegalArgumentException("Property '" + key + "' is not a single value property!"); 239 } 240 values = Collections.singletonList(value); 241 } 242 Object firstValue = values == null ? null : values.get(0); 243 244 if (pd instanceof PropertyStringDefinition) { 245 return of.createPropertyStringData(key, (List<String>) values); 246 } else if (pd instanceof PropertyIdDefinition) { 247 return of.createPropertyIdData(key, (List<String>) values); 248 } else if (pd instanceof PropertyHtmlDefinition) { 249 return of.createPropertyHtmlData(key, (List<String>) values); 250 } else if (pd instanceof PropertyUriDefinition) { 251 return of.createPropertyUriData(key, (List<String>) values); 252 } else if (pd instanceof PropertyIntegerDefinition) { 253 if (firstValue == null) { 254 return of.createPropertyIntegerData(key, (List<BigInteger>) null); 255 } else if (firstValue instanceof BigInteger) { 256 return of.createPropertyIntegerData(key, (List<BigInteger>) values); 257 } else if ((firstValue instanceof Byte) || (firstValue instanceof Short) || (firstValue instanceof Integer) 258 || (firstValue instanceof Long)) { 259 List<BigInteger> list = new ArrayList<BigInteger>(values.size()); 260 for (Object v : values) { 261 list.add(BigInteger.valueOf(((Number) v).longValue())); 262 } 263 return of.createPropertyIntegerData(key, list); 264 } else { 265 throw new IllegalArgumentException("Property '" + key + "' is an Integer property"); 266 } 267 } else if (pd instanceof PropertyBooleanDefinition) { 268 return of.createPropertyBooleanData(key, (List<Boolean>) values); 269 } else if (pd instanceof PropertyDecimalDefinition) { 270 return of.createPropertyDecimalData(key, (List<BigDecimal>) values); 271 } else if (pd instanceof PropertyDateTimeDefinition) { 272 return of.createPropertyDateTimeData(key, (List<GregorianCalendar>) values); 273 } 274 throw new CmisRuntimeException("Unknown class: " + pd.getClass().getName()); 275 } 276 277 @Override 278 public List<PropertyData<?>> convertQueryProperties(Properties properties) { 279 if (properties == null || properties.getProperties() == null) { 280 return null; 281 } 282 return new ArrayList<PropertyData<?>>(properties.getPropertyList()); 283 } 284 285 @Override 286 public QueryResult convertQueryResult(ObjectData objectData) { 287 throw new UnsupportedOperationException(); 288 } 289 290 @Override 291 public Rendition convertRendition(String objectId, RenditionData rendition) { 292 if (rendition == null) { 293 return null; 294 } 295 BigInteger rl = rendition.getBigLength(); 296 BigInteger rh = rendition.getBigHeight(); 297 BigInteger rw = rendition.getBigWidth(); 298 long length = rl == null ? -1 : rl.longValue(); 299 int height = rh == null ? -1 : rh.intValue(); 300 int width = rw == null ? -1 : rw.intValue(); 301 return new RenditionImpl(session, objectId, rendition.getStreamId(), rendition.getRenditionDocumentId(), 302 rendition.getKind(), length, rendition.getMimeType(), rendition.getTitle(), height, width); 303 } 304 305 @Override 306 public ObjectType convertTypeDefinition(TypeDefinition typeDefinition) { 307 if (typeDefinition instanceof DocumentTypeDefinition) { 308 return new DocumentTypeImpl(session, (DocumentTypeDefinition) typeDefinition); 309 } else if (typeDefinition instanceof FolderTypeDefinition) { 310 return new FolderTypeImpl(session, (FolderTypeDefinition) typeDefinition); 311 } else if (typeDefinition instanceof RelationshipTypeDefinition) { 312 return new RelationshipTypeImpl(session, (RelationshipTypeDefinition) typeDefinition); 313 } else if (typeDefinition instanceof PolicyTypeDefinition) { 314 return new PolicyTypeImpl(session, (PolicyTypeDefinition) typeDefinition); 315 } else if (typeDefinition instanceof SecondaryTypeDefinition) { 316 return new SecondaryTypeImpl(session, (SecondaryTypeDefinition) typeDefinition); 317 } 318 throw new CmisRuntimeException("Unknown base class: " + typeDefinition.getClass().getName()); 319 } 320 321 @Override 322 public ChangeEvent convertChangeEvent(ObjectData objectData) { 323 // TODO Auto-generated method stub 324 throw new UnsupportedOperationException(); 325 } 326 327 @Override 328 public ChangeEvents convertChangeEvents(String changeLogToken, ObjectList objectList) { 329 // TODO Auto-generated method stub 330 throw new UnsupportedOperationException(); 331 } 332 333}