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.math.BigInteger; 015import java.util.ArrayList; 016import java.util.Collection; 017import java.util.Collections; 018import java.util.List; 019import java.util.Locale; 020import java.util.Map; 021import java.util.Set; 022 023import org.apache.chemistry.opencmis.client.api.ChangeEvent; 024import org.apache.chemistry.opencmis.client.api.ChangeEvents; 025import org.apache.chemistry.opencmis.client.api.CmisObject; 026import org.apache.chemistry.opencmis.client.api.Document; 027import org.apache.chemistry.opencmis.client.api.Folder; 028import org.apache.chemistry.opencmis.client.api.ItemIterable; 029import org.apache.chemistry.opencmis.client.api.ObjectId; 030import org.apache.chemistry.opencmis.client.api.ObjectType; 031import org.apache.chemistry.opencmis.client.api.OperationContext; 032import org.apache.chemistry.opencmis.client.api.Policy; 033import org.apache.chemistry.opencmis.client.api.QueryResult; 034import org.apache.chemistry.opencmis.client.api.QueryStatement; 035import org.apache.chemistry.opencmis.client.api.Relationship; 036import org.apache.chemistry.opencmis.client.api.Session; 037import org.apache.chemistry.opencmis.client.api.Tree; 038import org.apache.chemistry.opencmis.client.runtime.ObjectIdImpl; 039import org.apache.chemistry.opencmis.client.runtime.OperationContextImpl; 040import org.apache.chemistry.opencmis.client.runtime.QueryResultImpl; 041import org.apache.chemistry.opencmis.client.runtime.QueryStatementImpl; 042import org.apache.chemistry.opencmis.client.runtime.util.AbstractPageFetcher; 043import org.apache.chemistry.opencmis.client.runtime.util.CollectionIterable; 044import org.apache.chemistry.opencmis.commons.PropertyIds; 045import org.apache.chemistry.opencmis.commons.data.Ace; 046import org.apache.chemistry.opencmis.commons.data.Acl; 047import org.apache.chemistry.opencmis.commons.data.BulkUpdateObjectIdAndChangeToken; 048import org.apache.chemistry.opencmis.commons.data.ContentStream; 049import org.apache.chemistry.opencmis.commons.data.FailedToDeleteData; 050import org.apache.chemistry.opencmis.commons.data.ObjectData; 051import org.apache.chemistry.opencmis.commons.data.ObjectList; 052import org.apache.chemistry.opencmis.commons.data.Properties; 053import org.apache.chemistry.opencmis.commons.data.PropertyData; 054import org.apache.chemistry.opencmis.commons.data.RepositoryInfo; 055import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition; 056import org.apache.chemistry.opencmis.commons.enums.AclPropagation; 057import org.apache.chemistry.opencmis.commons.enums.BindingType; 058import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships; 059import org.apache.chemistry.opencmis.commons.enums.RelationshipDirection; 060import org.apache.chemistry.opencmis.commons.enums.UnfileObject; 061import org.apache.chemistry.opencmis.commons.enums.VersioningState; 062import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; 063import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException; 064import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; 065import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException; 066import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlListImpl; 067import org.apache.chemistry.opencmis.commons.impl.dataobjects.BulkUpdateObjectIdAndChangeTokenImpl; 068import org.apache.chemistry.opencmis.commons.server.CallContext; 069import org.apache.chemistry.opencmis.commons.server.CmisService; 070import org.apache.commons.lang.StringUtils; 071import org.nuxeo.ecm.core.api.CoreSession; 072import org.nuxeo.ecm.core.api.DocumentModel; 073import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoObjectData; 074 075/** 076 * Nuxeo Persistent Session, having a direct connection to a Nuxeo {@link CoreSession}. 077 */ 078public class NuxeoSession implements Session { 079 080 private static final long serialVersionUID = 1L; 081 082 public static final OperationContext DEFAULT_CONTEXT = new OperationContextImpl(null, false, true, false, 083 IncludeRelationships.NONE, null, true, null, true, 10); 084 085 private final CoreSession coreSession; 086 087 private final String repositoryId; 088 089 protected final NuxeoObjectFactory objectFactory; 090 091 private final CmisService service; 092 093 private final NuxeoBinding binding; 094 095 private OperationContext defaultContext = DEFAULT_CONTEXT; 096 097 public NuxeoSession(NuxeoBinding binding, CallContext context) { 098 this.coreSession = binding.getCoreSession(); 099 repositoryId = context.getRepositoryId(); 100 objectFactory = new NuxeoObjectFactory(this); 101 service = binding.service; 102 this.binding = binding; 103 } 104 105 @Override 106 public NuxeoObjectFactory getObjectFactory() { 107 return objectFactory; 108 } 109 110 @Override 111 public NuxeoBinding getBinding() { 112 return binding; 113 } 114 115 public CmisService getService() { 116 return service; 117 } 118 119 protected CoreSession getCoreSession() { 120 return coreSession; 121 } 122 123 @Override 124 public void clear() { 125 } 126 127 public void save() { 128 coreSession.save(); 129 } 130 131 @Override 132 public void setDefaultContext(OperationContext defaultContext) { 133 this.defaultContext = defaultContext; 134 } 135 136 @Override 137 public OperationContext getDefaultContext() { 138 return defaultContext; 139 } 140 141 @Override 142 public Map<String, String> getSessionParameters() { 143 return Collections.emptyMap(); 144 } 145 146 protected String getRepositoryId() { 147 return coreSession.getRepositoryName(); 148 } 149 150 @Override 151 public ObjectId createObjectId(String id) { 152 return new ObjectIdImpl(id); 153 } 154 155 @Override 156 public ObjectId createDocument(Map<String, ?> properties, ObjectId folderId, ContentStream contentStream, 157 VersioningState versioningState) { 158 return createDocument(properties, folderId, contentStream, versioningState, null, null, null); 159 } 160 161 /** Converts from an untyped map to a {@link Properties} object. */ 162 protected Properties convertProperties(Map<String, ?> properties) { 163 if (properties == null) { 164 return null; 165 } 166 // find type 167 String typeId = (String) properties.get(PropertyIds.OBJECT_TYPE_ID); 168 if (typeId == null) { 169 throw new IllegalArgumentException("Missing type"); 170 } 171 ObjectType type = getTypeDefinition(typeId); 172 if (type == null) { 173 throw new IllegalArgumentException("Unknown type: " + typeId); 174 } 175 return objectFactory.convertProperties(properties, type, null, null); 176 } 177 178 @Override 179 public ObjectId createDocument(Map<String, ?> properties, ObjectId folderId, ContentStream contentStream, 180 VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces) { 181 String id = service.createDocument(repositoryId, convertProperties(properties), folderId == null ? null 182 : folderId.getId(), contentStream, versioningState, objectFactory.convertPolicies(policies), 183 objectFactory.convertAces(addAces), objectFactory.convertAces(removeAces), null); 184 return createObjectId(id); 185 } 186 187 @Override 188 public ObjectId createFolder(Map<String, ?> properties, ObjectId folderId) { 189 return createFolder(properties, folderId, null, null, null); 190 } 191 192 @Override 193 public ObjectId createFolder(Map<String, ?> properties, ObjectId folderId, List<Policy> policies, 194 List<Ace> addAces, List<Ace> removeAces) { 195 String id = service.createFolder(repositoryId, convertProperties(properties), folderId == null ? null 196 : folderId.getId(), objectFactory.convertPolicies(policies), objectFactory.convertAces(addAces), 197 objectFactory.convertAces(removeAces), null); 198 return createObjectId(id); 199 } 200 201 @Override 202 public OperationContext createOperationContext() { 203 return new OperationContextImpl(); 204 } 205 206 @Override 207 public OperationContext createOperationContext(Set<String> filter, boolean includeAcls, 208 boolean includeAllowableActions, boolean includePolicies, IncludeRelationships includeRelationships, 209 Set<String> renditionFilter, boolean includePathSegments, String orderBy, boolean cacheEnabled, 210 int maxItemsPerPage) { 211 // TODO Auto-generated method stub 212 throw new UnsupportedOperationException(); 213 } 214 215 @Override 216 public ObjectId createPolicy(Map<String, ?> properties, ObjectId folderId) { 217 return createPolicy(properties, folderId, null, null, null); 218 } 219 220 @Override 221 public ObjectId createPolicy(Map<String, ?> properties, ObjectId folderId, List<Policy> policies, 222 List<Ace> addAces, List<Ace> removeAces) { 223 // TODO Auto-generated method stub 224 throw new UnsupportedOperationException(); 225 } 226 227 @Override 228 public ObjectId createRelationship(Map<String, ?> properties) { 229 return createRelationship(properties, null, null, null); 230 } 231 232 @Override 233 public ObjectId createRelationship(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces, 234 List<Ace> removeAces) { 235 String id = service.createRelationship(repositoryId, convertProperties(properties), 236 objectFactory.convertPolicies(policies), objectFactory.convertAces(addAces), 237 objectFactory.convertAces(removeAces), null); 238 return createObjectId(id); 239 } 240 241 @Override 242 public ObjectId createItem(Map<String, ?> properties, ObjectId folderId, List<Policy> policies, List<Ace> addAces, 243 List<Ace> removeAces) { 244 throw new CmisNotSupportedException(); 245 } 246 247 @Override 248 public ObjectId createItem(Map<String, ?> properties, ObjectId folderId) { 249 throw new CmisNotSupportedException(); 250 } 251 252 @Override 253 public ObjectId createDocumentFromSource(ObjectId source, Map<String, ?> properties, ObjectId folderId, 254 VersioningState versioningState) { 255 return createDocumentFromSource(source, properties, folderId, versioningState, null, null, null); 256 } 257 258 @Override 259 public ObjectId createDocumentFromSource(ObjectId source, Map<String, ?> properties, ObjectId folderId, 260 VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces) { 261 // TODO Auto-generated method stub 262 throw new UnsupportedOperationException(); 263 } 264 265 @Override 266 public ItemIterable<Document> getCheckedOutDocs() { 267 // TODO Auto-generated method stub 268 throw new UnsupportedOperationException(); 269 } 270 271 @Override 272 public ItemIterable<Document> getCheckedOutDocs(OperationContext context) { 273 // TODO Auto-generated method stub 274 throw new UnsupportedOperationException(); 275 } 276 277 @Override 278 public ChangeEvents getContentChanges(String changeLogToken, boolean includeProperties, long maxNumItems) { 279 return getContentChanges(changeLogToken, includeProperties, maxNumItems, getDefaultContext()); 280 } 281 282 @Override 283 public ChangeEvents getContentChanges(String changeLogToken, boolean includeProperties, long maxNumItems, 284 OperationContext context) { 285 // TODO Auto-generated method stub 286 throw new UnsupportedOperationException(); 287 } 288 289 @Override 290 public ItemIterable<ChangeEvent> getContentChanges(String changeLogToken, boolean includeProperties) { 291 return getContentChanges(changeLogToken, includeProperties, getDefaultContext()); 292 }; 293 294 @Override 295 public ItemIterable<ChangeEvent> getContentChanges(String changeLogToken, boolean includeProperties, 296 OperationContext context) { 297 // TODO Auto-generated method stub 298 throw new UnsupportedOperationException(); 299 }; 300 301 @Override 302 public Locale getLocale() { 303 // TODO Auto-generated method stub 304 throw new UnsupportedOperationException(); 305 } 306 307 @Override 308 public boolean exists(ObjectId objectId) { 309 return exists(objectId.getId()); 310 } 311 312 @Override 313 public boolean exists(String objectId) { 314 try { 315 service.getObject(repositoryId, objectId, PropertyIds.OBJECT_ID, Boolean.FALSE, IncludeRelationships.NONE, 316 "cmis:none", Boolean.FALSE, Boolean.FALSE, null); 317 return true; 318 } catch (CmisObjectNotFoundException e) { 319 return false; 320 } 321 } 322 323 @Override 324 public boolean existsPath(String parentPath, String name) { 325 if (parentPath == null || !parentPath.startsWith("/")) { 326 throw new CmisInvalidArgumentException("Invalid parent path: " + parentPath); 327 } 328 if (StringUtils.isEmpty(name)) { 329 throw new CmisInvalidArgumentException("Invalid empty name: " + name); 330 } 331 StringBuilder path = new StringBuilder(parentPath); 332 if (!parentPath.endsWith("/")) { 333 path.append('/'); 334 } 335 path.append(name); 336 return existsPath(path.toString()); 337 } 338 339 @Override 340 public boolean existsPath(String path) { 341 try { 342 service.getObjectByPath(repositoryId, path, PropertyIds.OBJECT_ID, Boolean.FALSE, IncludeRelationships.NONE, 343 "cmis:none", Boolean.FALSE, Boolean.FALSE, null); 344 return true; 345 } catch (CmisObjectNotFoundException e) { 346 return false; 347 } 348 } 349 350 @Override 351 public CmisObject getObject(ObjectId objectId) { 352 return getObject(objectId, getDefaultContext()); 353 } 354 355 @Override 356 public CmisObject getObject(String objectId) { 357 return getObject(objectId, getDefaultContext()); 358 } 359 360 /** Gets a CMIS object given a Nuxeo {@link DocumentModel}. */ 361 public CmisObject getObject(DocumentModel doc, OperationContext context) { 362 ObjectData data = new NuxeoObjectData(service, doc, context); 363 return objectFactory.convertObject(data, context); 364 } 365 366 @Override 367 public CmisObject getObject(ObjectId objectId, OperationContext context) { 368 if (objectId == null) { 369 throw new CmisInvalidArgumentException("Missing object ID"); 370 } 371 return getObject(objectId.getId(), context); 372 } 373 374 @Override 375 public CmisObject getObject(String objectId, OperationContext context) { 376 if (objectId == null) { 377 throw new CmisInvalidArgumentException("Missing object ID"); 378 } 379 if (context == null) { 380 throw new CmisInvalidArgumentException("Missing operation context"); 381 } 382 ObjectData data = service.getObject(repositoryId, objectId, context.getFilterString(), 383 Boolean.valueOf(context.isIncludeAllowableActions()), context.getIncludeRelationships(), 384 context.getRenditionFilterString(), Boolean.valueOf(context.isIncludePolicies()), 385 Boolean.valueOf(context.isIncludeAcls()), null); 386 return objectFactory.convertObject(data, context); 387 } 388 389 @Override 390 public CmisObject getObjectByPath(String path) { 391 return getObjectByPath(path, getDefaultContext()); 392 } 393 394 @Override 395 public CmisObject getObjectByPath(String parentPath, String name) { 396 return getObjectByPath(parentPath, name, getDefaultContext()); 397 } 398 399 @Override 400 public CmisObject getObjectByPath(String parentPath, String name, OperationContext context) { 401 if (parentPath == null || !parentPath.startsWith("/")) { 402 throw new CmisInvalidArgumentException("Invalid parent path: " + parentPath); 403 } 404 if (StringUtils.isEmpty(name)) { 405 throw new CmisInvalidArgumentException("Invalid empty name: " + name); 406 } 407 StringBuilder path = new StringBuilder(parentPath); 408 if (!parentPath.endsWith("/")) { 409 path.append('/'); 410 } 411 path.append(name); 412 return getObjectByPath(path.toString(), context); 413 } 414 415 @Override 416 public CmisObject getObjectByPath(String path, OperationContext context) { 417 if (path == null || !path.startsWith("/")) { 418 throw new CmisInvalidArgumentException("Invalid path: " + path); 419 } 420 if (context == null) { 421 throw new CmisInvalidArgumentException("Missing operation context"); 422 } 423 ObjectData data = service.getObjectByPath(repositoryId, path, context.getFilterString(), 424 Boolean.valueOf(context.isIncludeAllowableActions()), context.getIncludeRelationships(), 425 context.getRenditionFilterString(), Boolean.valueOf(context.isIncludePolicies()), 426 Boolean.valueOf(context.isIncludeAcls()), null); 427 return getObjectFactory().convertObject(data, context); 428 } 429 430 @Override 431 public RepositoryInfo getRepositoryInfo() { 432 return service.getRepositoryInfo(repositoryId, null); 433 } 434 435 @Override 436 public Folder getRootFolder() { 437 return getRootFolder(getDefaultContext()); 438 } 439 440 @Override 441 public Folder getRootFolder(OperationContext context) { 442 String id = getRepositoryInfo().getRootFolderId(); 443 CmisObject folder = getObject(createObjectId(id), context); 444 if (!(folder instanceof Folder)) { 445 throw new CmisRuntimeException("Root object is not a Folder but: " + folder.getClass().getName()); 446 } 447 return (Folder) folder; 448 } 449 450 @Override 451 public ItemIterable<ObjectType> getTypeChildren(String typeId, boolean includePropertyDefinitions) { 452 // TODO Auto-generated method stub 453 throw new UnsupportedOperationException(); 454 } 455 456 @Override 457 public ObjectType getTypeDefinition(String typeId) { 458 TypeDefinition typeDefinition = service.getTypeDefinition(repositoryId, typeId, null); 459 return objectFactory.convertTypeDefinition(typeDefinition); 460 } 461 462 @Override 463 public ObjectType getTypeDefinition(String typeId, boolean useCache) { 464 return getTypeDefinition(typeId); 465 } 466 467 @Override 468 public List<Tree<ObjectType>> getTypeDescendants(String typeId, int depth, boolean includePropertyDefinitions) { 469 // TODO Auto-generated method stub 470 throw new UnsupportedOperationException(); 471 } 472 473 @Override 474 public ItemIterable<QueryResult> query(String statement, boolean searchAllVersions) { 475 // TODO Auto-generated method stub 476 throw new UnsupportedOperationException(); 477 } 478 479 @Override 480 public ItemIterable<QueryResult> query(final String statement, final boolean searchAllVersions, 481 final OperationContext context) { 482 AbstractPageFetcher<QueryResult> pageFetcher = new AbstractPageFetcher<QueryResult>( 483 context.getMaxItemsPerPage()) { 484 @Override 485 protected Page<QueryResult> fetchPage(long skipCount) { 486 ObjectList results = service.query(repositoryId, statement, Boolean.valueOf(searchAllVersions), 487 Boolean.valueOf(context.isIncludeAllowableActions()), context.getIncludeRelationships(), 488 context.getRenditionFilterString(), BigInteger.valueOf(maxNumItems), 489 BigInteger.valueOf(skipCount), null); 490 // convert objects 491 List<QueryResult> page = new ArrayList<QueryResult>(); 492 if (results.getObjects() != null) { 493 for (ObjectData data : results.getObjects()) { 494 page.add(new QueryResultImpl(NuxeoSession.this, data)); 495 } 496 } 497 return new Page<QueryResult>(page, results.getNumItems(), results.hasMoreItems()); 498 } 499 }; 500 return new CollectionIterable<QueryResult>(pageFetcher); 501 } 502 503 @Override 504 public ItemIterable<CmisObject> queryObjects(String typeId, String where, boolean searchAllVersions, 505 OperationContext context) { 506 // TODO Auto-generated method stub 507 throw new UnsupportedOperationException(); 508 } 509 510 @Override 511 public QueryStatement createQueryStatement(String statement) { 512 return new QueryStatementImpl(this, statement); 513 } 514 515 @Override 516 public QueryStatement createQueryStatement(Collection<String> selectPropertyIds, Map<String, String> fromTypes, 517 String whereClause, List<String> orderByPropertyIds) { 518 return new QueryStatementImpl(this, selectPropertyIds, fromTypes, whereClause, orderByPropertyIds); 519 } 520 521 @Override 522 public ItemIterable<Relationship> getRelationships(final ObjectId objectId, 523 final boolean includeSubRelationshipTypes, final RelationshipDirection relationshipDirection, 524 final ObjectType type, final OperationContext context) { 525 final String typeId = type == null ? null : type.getId(); 526 AbstractPageFetcher<Relationship> pageFetcher = new AbstractPageFetcher<Relationship>( 527 context.getMaxItemsPerPage()) { 528 @Override 529 protected Page<Relationship> fetchPage(long skipCount) { 530 ObjectList relations = service.getObjectRelationships(repositoryId, objectId.getId(), 531 Boolean.valueOf(includeSubRelationshipTypes), relationshipDirection, typeId, null, null, 532 BigInteger.valueOf(maxNumItems), BigInteger.valueOf(skipCount), null); 533 // convert objects 534 List<Relationship> page = new ArrayList<Relationship>(); 535 if (relations.getObjects() != null) { 536 for (ObjectData data : relations.getObjects()) { 537 CmisObject ob; 538 if (data instanceof NuxeoObjectData) { 539 ob = objectFactory.convertObject(data, context); 540 } else { 541 ob = getObject(data.getId(), context); 542 } 543 if (!(ob instanceof Relationship)) { 544 // should not happen... 545 continue; 546 } 547 page.add((Relationship) ob); 548 } 549 } 550 return new Page<Relationship>(page, relations.getNumItems(), relations.hasMoreItems()); 551 } 552 }; 553 return new CollectionIterable<Relationship>(pageFetcher); 554 } 555 556 @Override 557 public Acl getAcl(ObjectId objectId, boolean onlyBasicPermissions) { 558 return service.getAcl(repositoryId, objectId.getId(), Boolean.valueOf(onlyBasicPermissions), null); 559 } 560 561 @Override 562 public Acl setAcl(ObjectId objectId, List<Ace> aces) { 563 return service.applyAcl(repositoryId, objectId.getId(), new AccessControlListImpl(aces), null); 564 } 565 566 @Override 567 public Acl applyAcl(ObjectId objectId, List<Ace> addAces, List<Ace> removeAces, AclPropagation aclPropagation) { 568 return service.applyAcl(repositoryId, objectId.getId(), new AccessControlListImpl(addAces), 569 new AccessControlListImpl(removeAces), aclPropagation, null); 570 } 571 572 @Override 573 public void applyPolicy(ObjectId objectId, ObjectId... policyIds) { 574 throw new CmisNotSupportedException(); 575 } 576 577 @Override 578 public void removePolicy(ObjectId objectId, ObjectId... policyIds) { 579 throw new CmisNotSupportedException(); 580 } 581 582 @Override 583 public void removeObjectFromCache(ObjectId objectId) { 584 } 585 586 @Override 587 public void removeObjectFromCache(String objectId) { 588 } 589 590 @Override 591 public void delete(ObjectId objectId) { 592 delete(objectId, true); 593 } 594 595 @Override 596 public void delete(ObjectId objectId, boolean allVersions) { 597 service.deleteObject(repositoryId, objectId.getId(), Boolean.valueOf(allVersions), null); 598 } 599 600 @Override 601 public List<String> deleteTree(ObjectId folderId, boolean allVersions, UnfileObject unfile, 602 boolean continueOnFailure) { 603 FailedToDeleteData res = service.deleteTree(repositoryId, folderId.getId(), Boolean.valueOf(allVersions), 604 unfile, Boolean.valueOf(continueOnFailure), null); 605 return res.getIds(); 606 } 607 608 @Override 609 public ContentStream getContentStream(ObjectId docId) { 610 return getContentStream(docId, null, null, null); 611 } 612 613 @Override 614 public ContentStream getContentStream(ObjectId docId, String streamId, BigInteger offset, BigInteger length) { 615 if (docId == null) { 616 throw new CmisInvalidArgumentException("Missing object ID"); 617 } 618 return service.getContentStream(repositoryId, docId.getId(), streamId, offset, length, null); 619 } 620 621 @Override 622 public ObjectType createType(TypeDefinition type) { 623 throw new CmisNotSupportedException(); 624 } 625 626 @Override 627 public ObjectType updateType(TypeDefinition type) { 628 throw new CmisNotSupportedException(); 629 } 630 631 @Override 632 public void deleteType(String typeId) { 633 throw new CmisNotSupportedException(); 634 } 635 636 @Override 637 public List<BulkUpdateObjectIdAndChangeToken> bulkUpdateProperties(List<CmisObject> objects, 638 Map<String, ?> properties, List<String> addSecondaryTypeIds, List<String> removeSecondaryTypeIds) { 639 List<BulkUpdateObjectIdAndChangeToken> idts = new ArrayList<BulkUpdateObjectIdAndChangeToken>(objects.size()); 640 for (CmisObject object : objects) { 641 idts.add(new BulkUpdateObjectIdAndChangeTokenImpl(object.getId(), object.getChangeToken())); 642 } 643 return service.bulkUpdateProperties(repositoryId, idts, convertProperties(properties), addSecondaryTypeIds, 644 removeSecondaryTypeIds, null); 645 } 646 647 @Override 648 public Document getLatestDocumentVersion(ObjectId objectId) { 649 return getLatestDocumentVersion(objectId, false, getDefaultContext()); 650 } 651 652 @Override 653 public Document getLatestDocumentVersion(String objectId, OperationContext context) { 654 if (objectId == null) { 655 throw new IllegalArgumentException("Object ID must be set!"); 656 } 657 return getLatestDocumentVersion(createObjectId(objectId), false, context); 658 } 659 660 @Override 661 public Document getLatestDocumentVersion(String objectId, boolean major, OperationContext context) { 662 if (objectId == null) { 663 throw new IllegalArgumentException("Object ID must be set!"); 664 } 665 return getLatestDocumentVersion(createObjectId(objectId), major, context); 666 } 667 668 @Override 669 public Document getLatestDocumentVersion(String objectId) { 670 if (objectId == null) { 671 throw new IllegalArgumentException("Object ID must be set!"); 672 } 673 return getLatestDocumentVersion(createObjectId(objectId), false, getDefaultContext()); 674 } 675 676 @Override 677 public Document getLatestDocumentVersion(ObjectId objectId, OperationContext context) { 678 return getLatestDocumentVersion(objectId, false, context); 679 } 680 681 @Override 682 /** 683 * @See org.apache.chemistry.opencmis.client.runtime.SessionImpl 684 */ 685 public Document getLatestDocumentVersion(ObjectId objectId, boolean major, OperationContext context) { 686 if (objectId == null || objectId.getId() == null) { 687 throw new IllegalArgumentException("Object ID must be set!"); 688 } 689 690 if (context == null) { 691 throw new IllegalArgumentException("Operation context must be set!"); 692 } 693 694 CmisObject result = null; 695 696 String versionSeriesId = null; 697 698 // first attempt: if we got a Document object, try getting the version 699 // series ID from it 700 if (objectId instanceof Document) { 701 versionSeriesId = ((Document) objectId).getVersionSeriesId(); 702 } 703 704 // third attempt (Web Services only): get the version series ID from the 705 // repository 706 // (the AtomPub and Browser binding don't need the version series ID -> 707 // avoid roundtrip) 708 if (versionSeriesId == null) { 709 BindingType bindingType = getBinding().getBindingType(); 710 if (bindingType == BindingType.WEBSERVICES || bindingType == BindingType.CUSTOM) { 711 712 // get the document to find the version series ID 713 ObjectData sourceObjectData = binding.getObjectService().getObject(getRepositoryId(), objectId.getId(), 714 PropertyIds.OBJECT_ID + "," + PropertyIds.VERSION_SERIES_ID, false, IncludeRelationships.NONE, 715 "cmis:none", false, false, null); 716 717 if (sourceObjectData.getProperties() != null 718 && sourceObjectData.getProperties().getProperties() != null) { 719 PropertyData<?> verionsSeriesIdProp = sourceObjectData.getProperties().getProperties().get( 720 PropertyIds.VERSION_SERIES_ID); 721 if (verionsSeriesIdProp != null && verionsSeriesIdProp.getFirstValue() instanceof String) { 722 versionSeriesId = (String) verionsSeriesIdProp.getFirstValue(); 723 } 724 } 725 726 // the Web Services binding needs the version series ID -> fail 727 if (versionSeriesId == null) { 728 throw new IllegalArgumentException("Object is not a document or not versionable!"); 729 } 730 } 731 } 732 733 // get the object 734 ObjectData objectData = binding.getVersioningService().getObjectOfLatestVersion(getRepositoryId(), 735 objectId.getId(), versionSeriesId, major, context.getFilterString(), 736 context.isIncludeAllowableActions(), context.getIncludeRelationships(), 737 context.getRenditionFilterString(), context.isIncludePolicies(), context.isIncludeAcls(), null); 738 739 result = getObjectFactory().convertObject(objectData, context); 740 741 // check result 742 if (!(result instanceof Document)) { 743 throw new IllegalArgumentException("Latest version is not a document!"); 744 } 745 746 return (Document) result; 747 } 748 749 @Override 750 public String getLatestChangeLogToken() { 751 return getBinding().getRepositoryService().getRepositoryInfo(getRepositoryId(), null).getLatestChangeLogToken(); 752 } 753 754}