/*
* Copyright (c) 2006-2014 Nuxeo SA (http://nuxeo.com/) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Florent Guillaume
*/
package org.nuxeo.ecm.core.storage.sql.coremodel;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.nuxeo.ecm.core.api.DocumentException;
import org.nuxeo.ecm.core.api.Lock;
import org.nuxeo.ecm.core.api.model.DocumentPart;
import org.nuxeo.ecm.core.api.model.PropertyException;
import org.nuxeo.ecm.core.lifecycle.LifeCycleException;
import org.nuxeo.ecm.core.model.Document;
import org.nuxeo.ecm.core.model.Session;
import org.nuxeo.ecm.core.schema.DocumentType;
import org.nuxeo.ecm.core.schema.SchemaManager;
import org.nuxeo.ecm.core.schema.types.ComplexType;
import org.nuxeo.ecm.core.schema.types.Schema;
import org.nuxeo.ecm.core.storage.sql.Node;
import org.nuxeo.runtime.api.Framework;
/**
* A proxy is a shortcut to a target document (a version or normal document).
*/
public class SQLDocumentProxy implements SQLDocument {
/** The proxy seen as a normal doc ({@link SQLDocument}). */
private final Document proxy;
/** The target. */
private Document target;
// private SQLDocumentVersion version;
protected SQLDocumentProxy(Document proxy, Document target)
throws DocumentException {
this.proxy = proxy;
this.target = target;
}
protected String getSchema(String xpath) throws DocumentException {
int p = xpath.indexOf(':');
if (p == -1) {
throw new DocumentException("Schema not specified: " + xpath);
}
String prefix = xpath.substring(0, p);
SchemaManager schemaManager = Framework.getLocalService(SchemaManager.class);
Schema schema = schemaManager.getSchemaFromPrefix(prefix);
if (schema == null) {
schema = schemaManager.getSchema(prefix);
if (schema == null) {
throw new DocumentException("No schema for prefix: " + xpath);
}
}
return schema.getName();
}
/**
* Checks if the given schema should be resolved on the proxy or the target.
*/
protected boolean isSchemaForProxy(String schema) {
SchemaManager schemaManager = Framework.getLocalService(SchemaManager.class);
return schemaManager.isProxySchema(schema, getType().getName());
}
/**
* Checks if the given property should be resolved on the proxy or the
* target.
*/
protected boolean isPropertyForProxy(String xpath) throws DocumentException {
return isSchemaForProxy(getSchema(xpath));
}
/*
* ----- SQLDocument -----
*/
@Override
public Node getNode() {
return ((SQLDocument) proxy).getNode();
}
/*
* ----- Document -----
*/
@Override
public boolean isProxy() {
return true;
}
@Override
public String getUUID() {
return proxy.getUUID();
}
@Override
public String getName() {
return proxy.getName();
}
@Override
public Long getPos() {
return proxy.getPos();
}
@Override
public Document getParent() throws DocumentException {
return proxy.getParent();
}
@Override
public String getPath() throws DocumentException {
return proxy.getPath();
}
@Override
public void remove() throws DocumentException {
proxy.remove();
}
@Override
public DocumentType getType() {
return target.getType();
}
@Override
public String getRepositoryName() {
return target.getRepositoryName();
}
@Override
public Session getSession() {
return target.getSession();
}
@Override
public boolean isFolder() {
return target.isFolder();
}
@Override
public void setReadOnly(boolean readonly) {
target.setReadOnly(readonly);
}
@Override
public boolean isReadOnly() {
return target.isReadOnly();
}
@Override
public void readDocumentPart(DocumentPart dp) throws PropertyException {
if (isSchemaForProxy(dp.getName())) {
proxy.readDocumentPart(dp);
} else {
target.readDocumentPart(dp);
}
}
@Override
public Map<String, Serializable> readPrefetch(ComplexType complexType,
Set<String> xpaths) throws PropertyException {
if (isSchemaForProxy(complexType.getName())) {
return proxy.readPrefetch(complexType, xpaths);
} else {
return target.readPrefetch(complexType, xpaths);
}
}
@Override
public void writeDocumentPart(DocumentPart dp) throws PropertyException {
if (isSchemaForProxy(dp.getName())) {
proxy.writeDocumentPart(dp);
} else {
target.writeDocumentPart(dp);
}
}
@Override
public void setSystemProp(String name, Serializable value)
throws DocumentException {
target.setSystemProp(name, value);
}
@Override
public <T extends Serializable> T getSystemProp(String name, Class<T> type)
throws DocumentException {
return target.getSystemProp(name, type);
}
@Override
public Set<String> getAllFacets() {
return target.getAllFacets(); // TODO proxy facets
}
@Override
public String[] getFacets() {
return target.getFacets(); // TODO proxy facets
}
@Override
public boolean hasFacet(String facet) {
return target.hasFacet(facet); // TODO proxy facets
}
@Override
public boolean addFacet(String facet) throws DocumentException {
return target.addFacet(facet); // TODO proxy facets
}
@Override
public boolean removeFacet(String facet) throws DocumentException {
return target.removeFacet(facet); // TODO proxy facets
}
/*
* ----- LifeCycle -----
*/
@Override
public String getLifeCyclePolicy() throws LifeCycleException {
return target.getLifeCyclePolicy();
}
@Override
public void setLifeCyclePolicy(String policy) throws LifeCycleException {
target.setLifeCyclePolicy(policy);
}
@Override
public String getLifeCycleState() throws LifeCycleException {
return target.getLifeCycleState();
}
@Override
public void setCurrentLifeCycleState(String state)
throws LifeCycleException {
target.setCurrentLifeCycleState(state);
}
@Override
public void followTransition(String transition) throws LifeCycleException {
target.followTransition(transition);
}
@Override
public Collection<String> getAllowedStateTransitions()
throws LifeCycleException {
return target.getAllowedStateTransitions();
}
@Override
public Lock getLock() throws DocumentException {
return target.getLock();
}
@Override
public Lock setLock(Lock lock) throws DocumentException {
return target.setLock(lock);
}
@Override
public Lock removeLock(String owner) throws DocumentException {
return target.removeLock(owner);
}
@Override
public boolean isVersion() {
return false;
}
@Override
public Document getBaseVersion() throws DocumentException {
return null;
}
@Override
public String getVersionSeriesId() throws DocumentException {
return target.getVersionSeriesId();
}
@Override
public Document getSourceDocument() throws DocumentException {
// this is what the rest of Nuxeo expects for a proxy
return target;
}
@Override
public Document checkIn(String label, String checkinComment)
throws DocumentException {
throw new UnsupportedOperationException();
}
@Override
public void checkOut() throws DocumentException {
throw new UnsupportedOperationException();
}
@Override
public boolean isCheckedOut() throws DocumentException {
return target.isCheckedOut();
}
@Override
public boolean isLatestVersion() throws DocumentException {
return target.isLatestVersion();
}
@Override
public boolean isMajorVersion() throws DocumentException {
return target.isMajorVersion();
}
@Override
public boolean isLatestMajorVersion() throws DocumentException {
return target.isLatestMajorVersion();
}
@Override
public boolean isVersionSeriesCheckedOut() throws DocumentException {
return target.isVersionSeriesCheckedOut();
}
@Override
public String getVersionLabel() throws DocumentException {
return target.getVersionLabel();
}
@Override
public String getCheckinComment() throws DocumentException {
return target.getCheckinComment();
}
@Override
public Document getWorkingCopy() throws DocumentException {
return target.getWorkingCopy();
}
@Override
public Calendar getVersionCreationDate() throws DocumentException {
return target.getVersionCreationDate();
}
@Override
public void restore(Document version) throws DocumentException {
target.restore(version);
}
@Override
public List<String> getVersionsIds() throws DocumentException {
return target.getVersionsIds();
}
@Override
public Document getVersion(String label) throws DocumentException {
return target.getVersion(label);
}
@Override
public List<Document> getVersions() throws DocumentException {
return target.getVersions();
}
@Override
public Document getLastVersion() throws DocumentException {
return target.getLastVersion();
}
@Override
public Document getChild(String name) throws DocumentException {
return proxy.getChild(name);
}
@Override
public Iterator<Document> getChildren() throws DocumentException {
return proxy.getChildren();
}
@Override
public List<String> getChildrenIds() throws DocumentException {
return proxy.getChildrenIds();
}
@Override
public boolean hasChild(String name) throws DocumentException {
return proxy.hasChild(name);
}
@Override
public boolean hasChildren() throws DocumentException {
return proxy.hasChildren();
}
@Override
public Document addChild(String name, String typeName)
throws DocumentException {
return proxy.addChild(name, typeName);
}
@Override
public void orderBefore(String src, String dest) throws DocumentException {
proxy.orderBefore(src, dest);
}
/*
* ----- DocumentProxy -----
*/
@Override
public Document getTargetDocument() {
return target;
}
@Override
public void setTargetDocument(Document target) throws DocumentException {
if (((SQLDocumentLive) proxy).isReadOnly()) {
throw new DocumentException("Cannot write proxy: " + this);
}
if (!target.getVersionSeriesId().equals(getVersionSeriesId())) {
throw new DocumentException(
"Cannot set proxy target to different version series");
}
getSession().setProxyTarget(proxy, target);
this.target = target;
}
/*
* ----- PropertyContainer -----
*/
@Override
public Serializable getPropertyValue(String name) throws DocumentException {
if (isPropertyForProxy(name)) {
return proxy.getPropertyValue(name);
} else {
return target.getPropertyValue(name);
}
}
@Override
public void setPropertyValue(String name, Serializable value)
throws DocumentException {
if (isPropertyForProxy(name)) {
proxy.setPropertyValue(name, value);
} else {
target.setPropertyValue(name, value);
}
}
/*
* ----- toString/equals/hashcode -----
*/
@Override
public String toString() {
return getClass().getSimpleName() + '(' + target + ','
+ proxy.getUUID() + ')';
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if (other instanceof SQLDocumentProxy) {
return equals((SQLDocumentProxy) other);
}
return false;
}
private boolean equals(SQLDocumentProxy other) {
return proxy.equals(other.proxy) && target.equals(other.target);
}
@Override
public int hashCode() {
return proxy.hashCode() + target.hashCode();
}
}