001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Florent Guillaume 011 */ 012package org.nuxeo.ecm.core.opencmis.impl.client; 013 014import java.util.ArrayList; 015import java.util.Collection; 016import java.util.Collections; 017import java.util.GregorianCalendar; 018import java.util.HashMap; 019import java.util.List; 020import java.util.Map; 021import java.util.Map.Entry; 022import java.util.Set; 023 024import org.apache.chemistry.opencmis.client.api.CmisObject; 025import org.apache.chemistry.opencmis.client.api.ObjectId; 026import org.apache.chemistry.opencmis.client.api.ObjectType; 027import org.apache.chemistry.opencmis.client.api.Policy; 028import org.apache.chemistry.opencmis.client.api.Property; 029import org.apache.chemistry.opencmis.client.api.Relationship; 030import org.apache.chemistry.opencmis.client.api.Rendition; 031import org.apache.chemistry.opencmis.client.api.SecondaryType; 032import org.apache.chemistry.opencmis.client.runtime.RenditionImpl; 033import org.apache.chemistry.opencmis.commons.PropertyIds; 034import org.apache.chemistry.opencmis.commons.data.Ace; 035import org.apache.chemistry.opencmis.commons.data.Acl; 036import org.apache.chemistry.opencmis.commons.data.AllowableActions; 037import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement; 038import org.apache.chemistry.opencmis.commons.data.RenditionData; 039import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition; 040import org.apache.chemistry.opencmis.commons.enums.AclPropagation; 041import org.apache.chemistry.opencmis.commons.enums.Action; 042import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; 043import org.apache.chemistry.opencmis.commons.enums.ExtensionLevel; 044import org.apache.chemistry.opencmis.commons.enums.Updatability; 045import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException; 046import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException; 047import org.apache.chemistry.opencmis.commons.server.CmisService; 048import org.nuxeo.ecm.core.api.CoreSession; 049import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoCmisService; 050import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoObjectData; 051import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoPropertyData.NuxeoPropertyDataName; 052import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoPropertyDataBase; 053 054/** 055 * Base abstract live local CMIS Object, wrapping a {@link NuxeoSession} and a {@link NuxeoObjectData} which is backed 056 * by a Nuxeo document. 057 */ 058public abstract class NuxeoObject implements CmisObject { 059 060 protected static final Set<Updatability> UPDATABILITY_READWRITE = Collections.singleton(Updatability.READWRITE); 061 062 protected final NuxeoSession session; 063 064 protected final CmisService service; 065 066 protected final NuxeoCmisService nuxeoCmisService; 067 068 protected final NuxeoObjectFactory objectFactory; 069 070 public final NuxeoObjectData data; 071 072 protected final ObjectType type; 073 074 protected final List<SecondaryType> secondaryTypes; 075 076 /** type + secondaryTypes */ 077 protected final List<ObjectType> allTypes; 078 079 public static NuxeoObject construct(NuxeoSession session, NuxeoObjectData data, ObjectType type, 080 List<SecondaryType> secondaryTypes) { 081 BaseTypeId baseTypeId = type.getBaseTypeId(); 082 switch (baseTypeId) { 083 case CMIS_FOLDER: 084 return new NuxeoFolder(session, data, type, secondaryTypes); 085 case CMIS_DOCUMENT: 086 return new NuxeoDocument(session, data, type, secondaryTypes); 087 case CMIS_POLICY: 088 throw new UnsupportedOperationException(baseTypeId.toString()); 089 case CMIS_RELATIONSHIP: 090 return new NuxeoRelationship(session, data, type, secondaryTypes); 091 default: 092 throw new RuntimeException(baseTypeId.toString()); 093 } 094 } 095 096 public NuxeoObject(NuxeoSession session, NuxeoObjectData data, ObjectType type, 097 List<SecondaryType> secondaryTypes) { 098 this.session = session; 099 service = session.getService(); 100 nuxeoCmisService = NuxeoCmisService.extractFromCmisService(service); 101 objectFactory = session.getObjectFactory(); 102 this.data = data; 103 this.type = type; 104 this.secondaryTypes = secondaryTypes; 105 allTypes = new ArrayList<>(1 + secondaryTypes.size()); 106 allTypes.add(type); 107 allTypes.addAll(secondaryTypes); 108 } 109 110 @SuppressWarnings("unchecked") 111 @Override 112 public <T> T getAdapter(Class<T> adapterInterface) { 113 throw new CmisRuntimeException("Cannot adapt to " + adapterInterface.getName()); 114 } 115 116 public String getRepositoryId() { 117 return session.getRepositoryId(); 118 } 119 120 @Override 121 public String getId() { 122 return data.getId(); 123 } 124 125 @Override 126 public ObjectType getType() { 127 return type; 128 } 129 130 @Override 131 public BaseTypeId getBaseTypeId() { 132 return data.getBaseTypeId(); 133 } 134 135 @Override 136 public ObjectType getBaseType() { 137 return session.getTypeDefinition(getBaseTypeId().value()); 138 } 139 140 @Override 141 public List<SecondaryType> getSecondaryTypes() { 142 return secondaryTypes; 143 } 144 145 @Override 146 public List<ObjectType> findObjectType(String id) { 147 List<ObjectType> types = new ArrayList<>(1); 148 for (ObjectType t : allTypes) { 149 if (t.getPropertyDefinitions().containsKey(id)) { 150 types.add(t); 151 } 152 } 153 return types; 154 } 155 156 @Override 157 public String getName() { 158 return NuxeoPropertyDataName.getValue(data.doc); 159 } 160 161 @Override 162 public String getChangeToken() { 163 return getPropertyValue(PropertyIds.CHANGE_TOKEN); 164 } 165 166 @Override 167 public String getCreatedBy() { 168 return getPropertyValue(PropertyIds.CREATED_BY); 169 } 170 171 @Override 172 public GregorianCalendar getCreationDate() { 173 return getPropertyValue(PropertyIds.CREATION_DATE); 174 } 175 176 @Override 177 public GregorianCalendar getLastModificationDate() { 178 return getPropertyValue(PropertyIds.LAST_MODIFICATION_DATE); 179 } 180 181 @Override 182 public String getLastModifiedBy() { 183 return getPropertyValue(PropertyIds.LAST_MODIFIED_BY); 184 } 185 186 @Override 187 public String getDescription() { 188 return getPropertyValue(PropertyIds.DESCRIPTION); 189 } 190 191 @Override 192 public void delete(boolean allVersions) { 193 service.deleteObject(getRepositoryId(), getId(), Boolean.valueOf(allVersions), null); 194 } 195 196 @Override 197 public void delete() { 198 delete(true); 199 } 200 201 @Override 202 public CmisObject updateProperties(Map<String, ?> properties) { 203 ObjectId objectId = updateProperties(properties, true); 204 return session.getObject(objectId); 205 } 206 207 @Override 208 public ObjectId updateProperties(Map<String, ?> properties, boolean refresh) { 209 for (Entry<String, ?> en : properties.entrySet()) { 210 ((NuxeoPropertyDataBase<?>) data.getProperty(en.getKey())).setValue(en.getValue()); 211 } 212 CoreSession coreSession = session.getCoreSession(); 213 data.doc = coreSession.saveDocument(data.doc); 214 coreSession.save(); 215 return this; 216 } 217 218 @Override 219 public CmisObject rename(String newName) { 220 if (newName == null || newName.length() == 0) { 221 throw new IllegalArgumentException("New name must not be empty!"); 222 } 223 224 Map<String, Object> prop = new HashMap<String, Object>(); 225 prop.put(PropertyIds.NAME, newName); 226 227 return updateProperties(prop); 228 } 229 230 @Override 231 public ObjectId rename(String newName, boolean refresh) { 232 if (newName == null || newName.length() == 0) { 233 throw new IllegalArgumentException("New name must not be empty!"); 234 } 235 236 Map<String, Object> prop = new HashMap<String, Object>(); 237 prop.put(PropertyIds.NAME, newName); 238 239 return updateProperties(prop, refresh); 240 } 241 242 @SuppressWarnings("unchecked") 243 @Override 244 public <T> T getPropertyValue(String id) { 245 return (T) data.getProperty(id).getValue(); 246 } 247 248 @Override 249 public <T> Property<T> getProperty(String id) { 250 return new NuxeoProperty<T>(this, id); 251 } 252 253 @Override 254 public List<Property<?>> getProperties() { 255 List<Property<?>> list = new ArrayList<Property<?>>(); 256 for (ObjectType t : allTypes) { 257 Collection<PropertyDefinition<?>> defs = t.getPropertyDefinitions().values(); 258 for (PropertyDefinition<?> pd : defs) { 259 list.add(new NuxeoProperty<Object>(this, pd.getId())); 260 } 261 } 262 return list; 263 } 264 265 @Override 266 public Acl addAcl(List<Ace> addAces, AclPropagation aclPropagation) { 267 return service.applyAcl(getRepositoryId(), getId(), objectFactory.convertAces(addAces), null, aclPropagation, 268 null); 269 } 270 271 @Override 272 public Acl applyAcl(List<Ace> addAces, List<Ace> removeAces, AclPropagation aclPropagation) { 273 return service.applyAcl(getRepositoryId(), getId(), objectFactory.convertAces(addAces), 274 objectFactory.convertAces(removeAces), aclPropagation, null); 275 } 276 277 @Override 278 public Acl setAcl(List<Ace> aces) { 279 return service.applyAcl(getRepositoryId(), getId(), objectFactory.convertAces(aces), 280 AclPropagation.REPOSITORYDETERMINED); 281 } 282 283 @Override 284 public Acl getAcl() { 285 return data.getAcl(); 286 } 287 288 @Override 289 public Acl removeAcl(List<Ace> removeAces, AclPropagation aclPropagation) { 290 return service.applyAcl(getRepositoryId(), getId(), null, objectFactory.convertAces(removeAces), 291 aclPropagation, null); 292 } 293 294 @Override 295 public AllowableActions getAllowableActions() { 296 // we don't call data.getAllowableActions as includeAllowableActions 297 // may be false 298 return NuxeoObjectData.getAllowableActions(data.doc, data.creation); 299 } 300 301 @Override 302 public List<Policy> getPolicies() { 303 return Collections.emptyList(); 304 } 305 306 @Override 307 public void applyPolicy(ObjectId... policyIds) { 308 throw new CmisNotSupportedException(); 309 } 310 311 @Override 312 public void removePolicy(ObjectId... policyIds) { 313 throw new CmisNotSupportedException(); 314 } 315 316 @Override 317 public List<Relationship> getRelationships() { 318 throw new CmisNotSupportedException(); 319 } 320 321 @Override 322 public List<Rendition> getRenditions() { 323 List<RenditionData> renditions = data.getRenditions(); 324 if (renditions == null) { 325 return Collections.emptyList(); 326 } 327 List<Rendition> res = new ArrayList<Rendition>(renditions.size()); 328 for (RenditionData ren : renditions) { 329 long length = ren.getBigLength() == null ? -1 : ren.getBigLength().longValue(); 330 int height = ren.getBigHeight() == null ? -1 : ren.getBigHeight().intValue(); 331 int width = ren.getBigWidth() == null ? -1 : ren.getBigWidth().intValue(); 332 RenditionImpl rendition = new RenditionImpl(session, getId(), ren.getStreamId(), 333 ren.getRenditionDocumentId(), ren.getKind(), length, ren.getMimeType(), ren.getTitle(), height, 334 width); 335 res.add(rendition); 336 } 337 return res; 338 } 339 340 @Override 341 public void refresh() { 342 data.doc.refresh(); 343 } 344 345 @Override 346 public void refreshIfOld(long durationInMillis) { 347 // TODO Auto-generated method stub 348 throw new UnsupportedOperationException(); 349 } 350 351 @Override 352 public long getRefreshTimestamp() { 353 // TODO Auto-generated method stub 354 throw new UnsupportedOperationException(); 355 } 356 357 @Override 358 public List<CmisExtensionElement> getExtensions(ExtensionLevel level) { 359 // TODO Auto-generated method stub 360 throw new UnsupportedOperationException(); 361 } 362 363 @Override 364 public boolean hasAllowableAction(Action action) { 365 // TODO Auto-generated method stub 366 throw new UnsupportedOperationException(); 367 } 368 369 @Override 370 public Set<String> getPermissonsForPrincipal(String principalId) { 371 // TODO Auto-generated method stub 372 throw new UnsupportedOperationException(); 373 } 374 375 @Override 376 public Set<String> getPermissionsForPrincipal(String principalId) { 377 throw new UnsupportedOperationException(); 378 } 379 380 @Override 381 public void applyPolicy(ObjectId policyId, boolean refresh) { 382 throw new UnsupportedOperationException(); 383 } 384 385 @Override 386 public void removePolicy(ObjectId policyId, boolean refresh) { 387 throw new UnsupportedOperationException(); 388 } 389 390}