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