package org.etk.orm.core; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.jcr.Node; import javax.jcr.RepositoryException; import org.etk.common.logging.Logger; import org.etk.orm.api.Status; import org.etk.orm.api.UndeclaredRepositoryException; import org.etk.orm.plugins.bean.mapping.NodeAttributeType; import org.etk.orm.plugins.instrument.ProxyType; import org.etk.orm.plugins.jcr.LinkType; import org.etk.orm.plugins.jcr.type.PrimaryTypeInfo; import org.etk.orm.plugins.mapper.ObjectMapper; public final class EntityContext extends ObjectContext<EntityContext> { /** The logger. */ private static final Logger log = Logger.getLogger(EntityContext.class); /** The related type. */ final ObjectMapper<EntityContext> mapper; /** The object instance. */ final Object object; /** The related state. */ EntityContextState state; /** The attributes. */ private Map<Object, Object> attributes; EntityContext(ObjectMapper<EntityContext> mapper, EntityContextState state) throws RepositoryException { // Create our proxy ProxyType proxyType = state.getSession().domain.getProxyType(mapper.getObjectClass()); Object object = proxyType.createProxy(this); // this.state = null; this.mapper = mapper; this.object = object; this.state = state; this.attributes = null; } public Object getAttribute(Object key) { if (key == null) { throw new AssertionError("Should not provide a null key"); } if (attributes == null) { return null; } else { return attributes.get(key); } } public void setAttribute(Object key, Object value) { if (key == null) { throw new AssertionError("Should not provide a null key"); } if (value == null) { if (attributes != null) { attributes.remove(key); } } else { if (attributes == null) { attributes = new HashMap<Object, Object>(); } attributes.put(key, value); } } public Node getNode() { return state.getNode(); } public DomainSession getSession() { return state.getSession(); } public Status getStatus() { return state.getStatus(); } @Override public ObjectMapper<EntityContext> getMapper() { return mapper; } public Object getObject() { return object; } @Override public EntityContext getEntity() { return this; } public PrimaryTypeInfo getTypeInfo() { EntityContextState state = getEntity().state; return state.getTypeInfo(); } public String decodeName(String name, NameKind nameKind) { try { return state.getSession().getDomain().decodeName(this, name, nameKind); } catch (RepositoryException e) { throw new UndeclaredRepositoryException(e); } } public String encodeName(String name, NameKind nameKind) { try { return state.getSession().getDomain().encodeName(this, name, nameKind); } catch (RepositoryException e) { throw new UndeclaredRepositoryException(e); } } /** * Adapts the current object held by this context to the specified type. * If the current object is an instance of the specified class then this * object is returned otherwise an attempt to find an embedded object of * the specified type is performed. * * @param adaptedClass the class to adapt to * @param <T> the parameter type of the adapted class * @return the adapted object or null */ public <T> T adapt(Class<T> adaptedClass) { // If it fits the current object we use it if (adaptedClass.isInstance(object)) { return adaptedClass.cast(object); } else { // Here we are trying to see if the parent has something embedded we could return // that is would be of the provided related class EmbeddedContext embeddedCtx = getEmbedded(adaptedClass); if (embeddedCtx != null) { return adaptedClass.cast(embeddedCtx.getObject()); } } // return null; } public void addMixin(EmbeddedContext mixinCtx) { state.getSession().addMixin(this, mixinCtx); } public EmbeddedContext getEmbedded(Class<?> embeddedClass) { return state.getSession().getEmbedded(this, embeddedClass); } public String getAttribute(NodeAttributeType type) { DomainSession session = state.getSession(); switch (type) { case NAME: return session.getLocalName(this); case ID: return state.getId(); case PATH: return state.getPath(); case WORKSPACE_NAME: return session.sessionWrapper.getSession().getWorkspace().getName(); default: throw new AssertionError(); } } public void remove() { state.getSession().remove(this); } public <T> Iterator<T> getReferents(final String name, Class<T> filterClass, LinkType linkType) { return state.getSession().getReferents(this, name, filterClass, linkType); } public String getLocalName() { return getAttribute(NodeAttributeType.NAME); } public String getId() { return getAttribute(NodeAttributeType.ID); } public String getPath() { return getAttribute(NodeAttributeType.PATH); } public void setLocalName(String name) { state.getSession().setLocalName(this, name); } public EntityContext getReferenced(String name, LinkType linkType) { return state.getSession().getReferenced(this, name, linkType); } public void setReferenced(String name, EntityContext referencedCtx, LinkType linkType) { DomainSession session = state.getSession(); session.setReferenced(this, name, referencedCtx, linkType); } public boolean addReference(String name, EntityContext referentCtx, LinkType linkType) { DomainSession session = state.getSession(); return session.setReferenced(referentCtx, name, this, linkType); } public EntityContext getParent() { return state.getSession().getParent(this); } @Override public String toString() { return "EntityContext[state=" + state + ",mapper=" + mapper + "]"; } }