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 * Thomas Roger 011 * Dragos Mihalache 012 * Florent Guillaume 013 */ 014 015package org.nuxeo.ecm.core.api.impl; 016 017import static org.nuxeo.ecm.core.schema.types.ComplexTypeImpl.canonicalXPath; 018 019import java.io.Serializable; 020import java.util.Arrays; 021import java.util.Collection; 022import java.util.HashMap; 023import java.util.HashSet; 024import java.util.List; 025import java.util.Map; 026import java.util.Set; 027 028import org.nuxeo.common.collections.ScopeType; 029import org.nuxeo.common.collections.ScopedMap; 030import org.nuxeo.common.utils.Path; 031import org.nuxeo.ecm.core.api.CoreSession; 032import org.nuxeo.ecm.core.api.DataModel; 033import org.nuxeo.ecm.core.api.DataModelMap; 034import org.nuxeo.ecm.core.api.DocumentModel; 035import org.nuxeo.ecm.core.api.DocumentRef; 036import org.nuxeo.ecm.core.api.Lock; 037import org.nuxeo.ecm.core.api.PathRef; 038import org.nuxeo.ecm.core.api.PropertyException; 039import org.nuxeo.ecm.core.api.VersioningOption; 040import org.nuxeo.ecm.core.api.model.DocumentPart; 041import org.nuxeo.ecm.core.api.model.Property; 042import org.nuxeo.ecm.core.api.model.PropertyNotFoundException; 043import org.nuxeo.ecm.core.api.model.PropertyVisitor; 044import org.nuxeo.ecm.core.api.model.impl.DocumentPartImpl; 045import org.nuxeo.ecm.core.api.model.resolver.DocumentPropertyObjectResolverImpl; 046import org.nuxeo.ecm.core.api.model.resolver.PropertyObjectResolver; 047import org.nuxeo.ecm.core.api.security.ACP; 048import org.nuxeo.ecm.core.schema.DocumentType; 049import org.nuxeo.ecm.core.schema.SchemaManager; 050import org.nuxeo.ecm.core.schema.types.Schema; 051import org.nuxeo.runtime.api.Framework; 052 053/** 054 * A DocumentModel that can have any schema and is not made persistent by itself. A mockup to keep arbitrary schema 055 * data. 056 */ 057public class SimpleDocumentModel implements DocumentModel { 058 059 private static final long serialVersionUID = 1L; 060 061 protected final boolean anySchema; 062 063 protected final DataModelMap dataModels = new DataModelMapImpl(); 064 065 protected Set<String> schemas; 066 067 protected final ScopedMap contextData = new ScopedMap(); 068 069 protected Path path; 070 071 protected String type; 072 073 public SimpleDocumentModel(List<String> schemas) { 074 this.schemas = new HashSet<>(); 075 anySchema = false; 076 SchemaManager schemaManager = Framework.getLocalService(SchemaManager.class); 077 for (String schema : schemas) { 078 Schema s = schemaManager.getSchema(schema); 079 DocumentPart part = new DocumentPartImpl(s); 080 dataModels.put(schema, new DataModelImpl(part)); 081 this.schemas.add(schema); 082 } 083 } 084 085 public SimpleDocumentModel(String... schemas) { 086 this(Arrays.asList(schemas)); 087 } 088 089 public SimpleDocumentModel() { 090 schemas = new HashSet<>(); 091 anySchema = true; 092 } 093 094 /** 095 * A data model that is not tied to a particular schema, neither has anything to do with a session (CoreSession). 096 * 097 * @deprecated since 5.7.3. Use standard {@link DataModelImpl} instead. 098 */ 099 @Deprecated 100 public static class SimpleDataModel implements DataModel { 101 102 private static final long serialVersionUID = 1L; 103 104 public final String schema; 105 106 public final Map<String, Object> data = new HashMap<String, Object>(); 107 108 public SimpleDataModel(String schema) { 109 this.schema = schema; 110 } 111 112 @Override 113 public void setData(String key, Object value) throws PropertyException { 114 data.put(key, value); 115 } 116 117 @Override 118 public Object getData(String key) throws PropertyException { 119 return data.get(key); 120 } 121 122 @Override 123 public String getSchema() { 124 return schema; 125 } 126 127 @Override 128 public Map<String, Object> getMap() throws PropertyException { 129 return data; 130 } 131 132 @Override 133 public void setMap(Map<String, Object> data) throws PropertyException { 134 data = new HashMap<String, Object>(data); 135 } 136 137 @Override 138 public boolean isDirty() { 139 return true; 140 } 141 142 @Override 143 public boolean isDirty(String name) throws PropertyNotFoundException { 144 return true; 145 } 146 147 @Override 148 public void setDirty(String name) throws PropertyNotFoundException { 149 } 150 151 @Override 152 public Collection<String> getDirtyFields() { 153 return data.keySet(); 154 } 155 156 @Override 157 public Object getValue(String path) throws PropertyException { 158 throw new UnsupportedOperationException("getValue"); 159 } 160 161 @Override 162 public Object setValue(String path, Object value) throws PropertyException { 163 throw new UnsupportedOperationException("setValue"); 164 } 165 } 166 167 protected DataModel getDataModelInternal(String schema) { 168 DataModel dm = dataModels.get(schema); 169 if (dm == null && anySchema) { 170 SchemaManager schemaManager = Framework.getLocalService(SchemaManager.class); 171 Schema s = schemaManager.getSchema(schema); 172 DocumentPart part = new DocumentPartImpl(s); 173 dm = new DataModelImpl(part); 174 dataModels.put(schema, dm); 175 schemas.add(schema); 176 } 177 return dm; 178 } 179 180 @Override 181 public String[] getSchemas() { 182 Set<String> keys = dataModels.keySet(); 183 return keys.toArray(new String[keys.size()]); 184 } 185 186 @Override 187 public String[] getDeclaredSchemas() { 188 return getSchemas(); 189 } 190 191 @Override 192 public Object getProperty(String schemaName, String name) { 193 DataModel dm = getDataModelInternal(schemaName); 194 return dm != null ? dm.getData(name) : null; 195 } 196 197 @Override 198 public void setProperty(String schemaName, String name, Object value) { 199 if (name.contains(":")) { 200 name = name.substring(name.indexOf(":"), name.length()); 201 } 202 getDataModelInternal(schemaName).setData(name, value); 203 } 204 205 @Override 206 public Map<String, Object> getProperties(String schemaName) { 207 return getDataModelInternal(schemaName).getMap(); 208 } 209 210 @Override 211 public void setProperties(String schemaName, Map<String, Object> data) { 212 DataModel dm = getDataModelInternal(schemaName); 213 dm.setMap(data); 214 // force dirty for updated properties 215 for (String field : data.keySet()) { 216 dm.setDirty(field); 217 } 218 } 219 220 @Override 221 public ScopedMap getContextData() { 222 return contextData; 223 } 224 225 @Override 226 public Serializable getContextData(ScopeType scope, String key) { 227 return contextData.getScopedValue(scope, key); 228 } 229 230 @Override 231 public void putContextData(ScopeType scope, String key, Serializable value) { 232 contextData.putScopedValue(scope, key, value); 233 } 234 235 @Override 236 public Serializable getContextData(String key) { 237 return contextData.getScopedValue(key); 238 } 239 240 @Override 241 public void putContextData(String key, Serializable value) { 242 contextData.putScopedValue(key, value); 243 } 244 245 @Override 246 public void copyContextData(DocumentModel otherDocument) { 247 ScopedMap otherMap = otherDocument.getContextData(); 248 if (otherMap != null) { 249 contextData.putAll(otherMap); 250 } 251 } 252 253 @Override 254 public Property getProperty(String xpath) throws PropertyException { 255 if (xpath == null) { 256 throw new PropertyNotFoundException("null", "Invalid null xpath"); 257 } 258 String cxpath = canonicalXPath(xpath); 259 if (cxpath.isEmpty()) { 260 throw new PropertyNotFoundException(xpath, "Schema not specified"); 261 } 262 String schemaName = DocumentModelImpl.getXPathSchemaName(cxpath, schemas, null); 263 if (schemaName == null) { 264 if (cxpath.indexOf(':') != -1) { 265 throw new PropertyNotFoundException(xpath, "No such schema"); 266 } else { 267 throw new PropertyNotFoundException(xpath); 268 } 269 270 } 271 DocumentPart part = getPart(schemaName); 272 if (part == null) { 273 throw new PropertyNotFoundException(xpath); 274 } 275 // cut prefix 276 String partPath = cxpath.substring(cxpath.indexOf(':') + 1); 277 try { 278 Property property = part.resolvePath(partPath); 279 // force dirty for updated properties 280 property.setForceDirty(true); 281 return property; 282 } catch (PropertyNotFoundException e) { 283 throw new PropertyNotFoundException(xpath, e.getDetail()); 284 } 285 } 286 287 @Override 288 public Serializable getPropertyValue(String xpath) throws PropertyException { 289 return getProperty(xpath).getValue(); 290 } 291 292 @Override 293 public void setPropertyValue(String xpath, Serializable value) { 294 getProperty(xpath).setValue(value); 295 } 296 297 @Override 298 public DocumentType getDocumentType() { 299 throw new UnsupportedOperationException(); 300 } 301 302 @Override 303 public String getSessionId() { 304 throw new UnsupportedOperationException(); 305 } 306 307 @Override 308 public CoreSession getCoreSession() { 309 throw new UnsupportedOperationException(); 310 } 311 312 @Override 313 public void detach(boolean loadAll) { 314 } 315 316 @Override 317 public void attach(String sid) { 318 } 319 320 @Override 321 public DocumentRef getRef() { 322 throw new UnsupportedOperationException(); 323 } 324 325 @Override 326 public DocumentRef getParentRef() { 327 if (path == null) { 328 return null; 329 } 330 if (!path.isAbsolute()) { 331 return null; 332 } 333 return new PathRef(path.removeLastSegments(1).toString()); 334 } 335 336 @Override 337 public String getId() { 338 throw new UnsupportedOperationException(); 339 } 340 341 @Override 342 public String getName() { 343 return path == null ? null : path.lastSegment(); 344 } 345 346 @Override 347 public Long getPos() { 348 return null; 349 } 350 351 @Override 352 public String getPathAsString() { 353 return path == null ? null : path.toString(); 354 } 355 356 @Override 357 public Path getPath() { 358 return path; 359 } 360 361 @Override 362 public String getTitle() { 363 throw new UnsupportedOperationException(); 364 } 365 366 @Override 367 public String getType() { 368 return type; 369 } 370 371 public void setType(String type) { 372 this.type = type; 373 } 374 375 @Override 376 public Set<String> getFacets() { 377 throw new UnsupportedOperationException(); 378 } 379 380 @Override 381 public Set<String> getDeclaredFacets() { 382 return getFacets(); 383 } 384 385 @Override 386 public Collection<DataModel> getDataModelsCollection() { 387 throw new UnsupportedOperationException(); 388 } 389 390 @Override 391 public DataModelMap getDataModels() { 392 return dataModels; 393 } 394 395 @Override 396 public DataModel getDataModel(String schema) { 397 return getDataModelInternal(schema); 398 } 399 400 @Override 401 public void setPathInfo(String parentPath, String name) { 402 path = new Path(parentPath == null ? name : parentPath + '/' + name); 403 } 404 405 @Override 406 public String getLock() { 407 throw new UnsupportedOperationException(); 408 } 409 410 @Override 411 public boolean isLocked() { 412 throw new UnsupportedOperationException(); 413 } 414 415 @Override 416 public void setLock(String key) { 417 throw new UnsupportedOperationException(); 418 } 419 420 @Override 421 public void unlock() { 422 throw new UnsupportedOperationException(); 423 } 424 425 @Override 426 public Lock setLock() { 427 throw new UnsupportedOperationException(); 428 } 429 430 @Override 431 public Lock getLockInfo() { 432 throw new UnsupportedOperationException(); 433 } 434 435 @Override 436 public Lock removeLock() { 437 throw new UnsupportedOperationException(); 438 } 439 440 @Override 441 public ACP getACP() { 442 throw new UnsupportedOperationException(); 443 } 444 445 @Override 446 public void setACP(ACP acp, boolean overwrite) { 447 throw new UnsupportedOperationException(); 448 } 449 450 @Override 451 public boolean hasSchema(String schema) { 452 throw new UnsupportedOperationException(); 453 } 454 455 @Override 456 public boolean hasFacet(String facet) { 457 throw new UnsupportedOperationException(); 458 } 459 460 @Override 461 public boolean addFacet(String facet) { 462 throw new UnsupportedOperationException(); 463 } 464 465 @Override 466 public boolean removeFacet(String facet) { 467 throw new UnsupportedOperationException(); 468 } 469 470 @Override 471 public boolean isFolder() { 472 throw new UnsupportedOperationException(); 473 } 474 475 @Override 476 public boolean isVersionable() { 477 throw new UnsupportedOperationException(); 478 } 479 480 @Override 481 public boolean isDownloadable() { 482 throw new UnsupportedOperationException(); 483 } 484 485 @Override 486 public boolean isVersion() { 487 throw new UnsupportedOperationException(); 488 } 489 490 @Override 491 public boolean isProxy() { 492 throw new UnsupportedOperationException(); 493 } 494 495 @Override 496 public boolean isImmutable() { 497 throw new UnsupportedOperationException(); 498 } 499 500 @Override 501 public boolean isDirty() { 502 throw new UnsupportedOperationException(); 503 } 504 505 @Override 506 public void accept(PropertyVisitor visitor, Object arg) { 507 throw new UnsupportedOperationException(); 508 } 509 510 @Override 511 public <T> T getAdapter(Class<T> itf) { 512 throw new UnsupportedOperationException(); 513 } 514 515 @Override 516 public <T> T getAdapter(Class<T> itf, boolean refreshCache) { 517 throw new UnsupportedOperationException(); 518 } 519 520 @Override 521 public String getCurrentLifeCycleState() { 522 throw new UnsupportedOperationException(); 523 } 524 525 @Override 526 public String getLifeCyclePolicy() { 527 throw new UnsupportedOperationException(); 528 } 529 530 @Override 531 public boolean followTransition(String transition) { 532 throw new UnsupportedOperationException(); 533 } 534 535 @Override 536 public Collection<String> getAllowedStateTransitions() { 537 throw new UnsupportedOperationException(); 538 } 539 540 @Override 541 public void copyContent(DocumentModel sourceDoc) { 542 throw new UnsupportedOperationException(); 543 } 544 545 @Override 546 public String getRepositoryName() { 547 throw new UnsupportedOperationException(); 548 } 549 550 @Override 551 public String getCacheKey() { 552 throw new UnsupportedOperationException(); 553 } 554 555 @Override 556 public String getSourceId() { 557 throw new UnsupportedOperationException(); 558 } 559 560 @Override 561 public String getVersionLabel() { 562 throw new UnsupportedOperationException(); 563 } 564 565 @Override 566 public String getCheckinComment() { 567 throw new UnsupportedOperationException(); 568 } 569 570 @Override 571 public boolean isPrefetched(String xpath) { 572 return false; 573 } 574 575 @Override 576 public boolean isPrefetched(String schemaName, String name) { 577 return false; 578 } 579 580 @Override 581 public void prefetchCurrentLifecycleState(String lifecycle) { 582 throw new UnsupportedOperationException(); 583 } 584 585 @Override 586 public void prefetchLifeCyclePolicy(String lifeCyclePolicy) { 587 throw new UnsupportedOperationException(); 588 } 589 590 @Override 591 public boolean isLifeCycleLoaded() { 592 return false; 593 } 594 595 @Override 596 public <T extends Serializable> T getSystemProp(String systemProperty, Class<T> type) { 597 throw new UnsupportedOperationException(); 598 } 599 600 @Override 601 public DocumentPart getPart(String schema) { 602 DataModel dm = getDataModel(schema); 603 if (dm != null) { 604 return ((DataModelImpl) dm).getDocumentPart(); 605 } 606 return null; 607 } 608 609 @Override 610 public DocumentPart[] getParts() { 611 throw new UnsupportedOperationException(); 612 } 613 614 @Override 615 public void reset() { 616 throw new UnsupportedOperationException(); 617 } 618 619 @Override 620 public void refresh(int refreshFlags, String[] schemas) { 621 throw new UnsupportedOperationException(); 622 } 623 624 @Override 625 public void refresh() { 626 throw new UnsupportedOperationException(); 627 } 628 629 @Override 630 public DocumentModel clone() throws CloneNotSupportedException { 631 throw new UnsupportedOperationException(); 632 } 633 634 @Override 635 public boolean isCheckedOut() { 636 throw new UnsupportedOperationException(); 637 } 638 639 @Override 640 public void checkOut() { 641 throw new UnsupportedOperationException(); 642 } 643 644 @Override 645 public DocumentRef checkIn(VersioningOption option, String description) { 646 throw new UnsupportedOperationException(); 647 } 648 649 @Override 650 public String getVersionSeriesId() { 651 throw new UnsupportedOperationException(); 652 } 653 654 @Override 655 public boolean isLatestVersion() { 656 return false; 657 } 658 659 @Override 660 public boolean isMajorVersion() { 661 return false; 662 } 663 664 @Override 665 public boolean isLatestMajorVersion() { 666 return false; 667 } 668 669 @Override 670 public boolean isVersionSeriesCheckedOut() { 671 return true; 672 } 673 674 @Override 675 public String getChangeToken() { 676 return null; 677 } 678 679 @Override 680 public Map<String, String> getBinaryFulltext() { 681 return null; 682 } 683 684 @Override 685 public PropertyObjectResolver getObjectResolver(String xpath) { 686 return DocumentPropertyObjectResolverImpl.create(this, xpath); 687 } 688 689}