package org.wyona.yarep.impl; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.wyona.commons.io.PathUtil; import org.wyona.yarep.core.NoSuchNodeException; import org.wyona.yarep.core.NoSuchPropertyException; import org.wyona.yarep.core.NoSuchRevisionException; import org.wyona.yarep.core.Node; import org.wyona.yarep.core.NodeStateException; import org.wyona.yarep.core.NodeType; import org.wyona.yarep.core.Property; import org.wyona.yarep.core.PropertyType; import org.wyona.yarep.core.Repository; import org.wyona.yarep.core.RepositoryException; import org.wyona.yarep.core.Revision; /** * This class represents a repository node and implements some basic functionality which may be * shared among different implementations. */ public abstract class AbstractNode implements Node { private static Logger log = LogManager.getLogger(AbstractNode.class); protected Repository repository; protected String path; protected String name; protected String uuid; protected HashMap properties; protected LinkedHashMap revisions; // system properties: public static final String PROPERTY_TYPE = "yarep_type"; //public static final String PROPERTY_CONTENT = "yarep_content"; public static final String PROPERTY_SIZE = "yarep_size"; //public static final String PROPERTY_LAST_MODIFIED = "yarep_lastModifed"; // INFO: Typo, but maybe needs to be re-introduced because of backwards compatibility public static final String PROPERTY_LAST_MODIFIED = "yarep_lastModified"; public static final String PROPERTY_MIME_TYPE = "yarep_mimeType"; public static final String PROPERTY_ENCODING = "yarep_encoding"; public static final String PROPERTY_IS_CHECKED_OUT = "yarep_isCheckedOut"; public static final String PROPERTY_CHECKOUT_USER_ID = "yarep_checkoutUserID"; public static final String PROPERTY_CHECKOUT_DATE = "yarep_checkoutDate"; public static final String PROPERTY_CHECKIN_DATE = "yarep_checkinDate"; /** * Constructor * @throws RepositoryException */ public AbstractNode() throws RepositoryException { } /** * Constructor * @throws RepositoryException */ public AbstractNode(Repository repository, String path, String uuid) throws RepositoryException { this.repository = repository; this.path = path; this.name = PathUtil.getName(path); this.uuid = uuid; // TODO: Make sure that no backslashes are being used if (path.indexOf("\\") >= 0) { RepositoryException e = new RepositoryException("path contains backslashes: " + path); log.error(e.getMessage(), e); throw e; } } /** * @see org.wyona.yarep.core.Node#getName() */ public String getName() throws RepositoryException { return this.name; } /** * @see org.wyona.yarep.core.Node#getParent() */ public Node getParent() throws RepositoryException { if (getPath().equals("") || getPath().equals("/")) return null; String parentPath = PathUtil.getParent(path); return this.repository.getNode(parentPath); } /** * @see org.wyona.yarep.core.Node#getPath() */ public String getPath() throws RepositoryException { return this.path; } /** * @see org.wyona.yarep.core.Node#getUUID() */ public String getUUID() throws RepositoryException { return this.uuid; } /** * @see org.wyona.yarep.core.Node#getType() */ public int getType() throws RepositoryException { return NodeType.getType(getProperty(PROPERTY_TYPE).getString()); } /** * @see org.wyona.yarep.core.Node#isResource() */ public boolean isResource() throws RepositoryException { return getType() == NodeType.RESOURCE; } /** * @see org.wyona.yarep.core.Node#isCollection() */ public boolean isCollection() throws RepositoryException { //log.debug("Node Type: " + getType() + ", Path: " + getPath()); return getType() == NodeType.COLLECTION; } /** * @see org.wyona.yarep.core.Node#getNode(java.lang.String) */ public Node getNode(String name) throws NoSuchNodeException, RepositoryException { String base = getPath(); if (!base.endsWith("/")) { base = base + "/"; } String childPath = base + name; return this.repository.getNode(childPath); } /** * @see org.wyona.yarep.core.Node#hasNode(java.lang.String) */ public boolean hasNode(String name) throws RepositoryException { String base = getPath(); if (!base.endsWith("/")) { base = base + "/"; } String childPath = base + name; return this.repository.existsNode(childPath); } /** * @see org.wyona.yarep.core.Node#getProperty(java.lang.String) */ public Property getProperty(String name) throws RepositoryException { return (Property)this.properties.get(name); } /** * @see org.wyona.yarep.core.Node#getProperties() */ public Property[] getProperties() throws RepositoryException { return (Property[])this.properties.values().toArray(new Property[this.properties.size()]); } /** * @see org.wyona.yarep.core.Node#hasProperty(java.lang.String) */ public boolean hasProperty(String name) throws RepositoryException { return this.properties.containsKey(name); } //public boolean hasProperties() throws RepositoryException; /** * @see org.wyona.yarep.core.Node#setProperty(java.lang.String, boolean) */ public Property setProperty(String name, boolean value) throws RepositoryException { Property property = new DefaultProperty(name, PropertyType.BOOLEAN, this); property.setValue(value); setProperty(property); return property; } /** * @see org.wyona.yarep.core.Node#setProperty(java.lang.String, java.util.Date) */ public Property setProperty(String name, Date value) throws RepositoryException { Property property = new DefaultProperty(name, PropertyType.DATE, this); property.setValue(value); setProperty(property); return property; } /** * @see org.wyona.yarep.core.Node#setProperty(java.lang.String, double) */ public Property setProperty(String name, double value) throws RepositoryException { Property property = new DefaultProperty(name, PropertyType.DOUBLE, this); property.setValue(value); setProperty(property); return property; } //public Property setProperty(String name, InputStream value) throws RepositoryException; /** * @see org.wyona.yarep.core.Node#setProperty(java.lang.String, long) */ public Property setProperty(String name, long value) throws RepositoryException { Property property = new DefaultProperty(name, PropertyType.LONG, this); property.setValue(value); setProperty(property); return property; } /** * @see org.wyona.yarep.core.Node#setProperty(java.lang.String, java.lang.String) */ public Property setProperty(String name, String value) throws RepositoryException { //log.debug("Set property: " + name + ", " + value); Property property = new DefaultProperty(name, PropertyType.STRING, this); property.setValue(value); setProperty(property); return property; } /** * @see org.wyona.yarep.core.Node#isCheckedOut() */ public boolean isCheckedOut() throws RepositoryException { if (!hasProperty(PROPERTY_IS_CHECKED_OUT)) { return false; } return getProperty(PROPERTY_IS_CHECKED_OUT).getBoolean(); } /** * @see org.wyona.yarep.core.Node#getCheckoutUserID() */ public String getCheckoutUserID() throws NodeStateException, RepositoryException { if (!isCheckedOut()) { throw new NodeStateException("Node is not checked out: " + getPath()); } return getProperty(PROPERTY_CHECKOUT_USER_ID).getString(); } /** * @see org.wyona.yarep.core.Node#getCheckoutDate() */ public Date getCheckoutDate() throws NodeStateException, RepositoryException { if (!isCheckedOut()) { throw new NodeStateException("Node is not checked out: " + getPath()); } return getProperty(PROPERTY_CHECKOUT_DATE).getDate(); } /** * @see org.wyona.yarep.core.Node#getCheckinDate() */ public Date getCheckinDate() throws NodeStateException, RepositoryException { if (isCheckedOut()) { throw new NodeStateException("Node is not checked in: " + getPath()); } return getProperty(PROPERTY_CHECKIN_DATE).getDate(); } /** * @see org.wyona.yarep.core.Node#getRevisions() */ public Revision[] getRevisions() throws RepositoryException { if (log.isDebugEnabled()) log.debug("Return already instantiated revisions ..."); Collection values = this.revisions.values(); return (Revision[])values.toArray(new Revision[values.size()]); } /** * @see org.wyona.yarep.core.Node#getRevision(java.lang.String) */ public Revision getRevision(String revisionName) throws NoSuchRevisionException, RepositoryException { if (!this.revisions.containsKey(revisionName)) { throw new NoSuchRevisionException("Node " + getPath() + " has no revision with name: " + revisionName); } return (Revision)this.revisions.get(revisionName); } /** * @see org.wyona.yarep.core.Node#getRevisionByTag(java.lang.String) */ public Revision getRevisionByTag(String tag) throws NoSuchRevisionException, RepositoryException { Iterator iter = this.revisions.values().iterator(); while (iter.hasNext()) { Revision revision = (Revision)iter.next(); if (revision.hasTag() && revision.getTag().equals(tag)) { return revision; } } // revision not found: throw new NoSuchRevisionException("Node " + getPath() + " has no revision with tag: " + tag); } /** * @see org.wyona.yarep.core.Node#hasRevisionWithTag(java.lang.String) */ public boolean hasRevisionWithTag(String tag) throws RepositoryException { Iterator iter = this.revisions.values().iterator(); while (iter.hasNext()) { Revision revision = (Revision)iter.next(); if (revision.hasTag() && revision.getTag().equals(tag)) { return true; } } // revision not found: return false; } /** * @see org.wyona.yarep.core.Node#getLastModified() */ public long getLastModified() throws RepositoryException { Property lastModified = getProperty(PROPERTY_LAST_MODIFIED); if (lastModified != null) { return lastModified.getLong(); } else { //log.warn("No last modified set: " + getPath()); return 0; } } /** * @see org.wyona.yarep.core.Node#getSize() */ public long getSize() throws RepositoryException { Property size = getProperty(PROPERTY_SIZE); if (size != null) { return size.getLong(); } else { return 0; } } /** * @see org.wyona.yarep.core.Node#getMimeType() */ public String getMimeType() throws RepositoryException { Property mimeType = getProperty(PROPERTY_MIME_TYPE); if (mimeType != null) { return mimeType.getString(); } else { return null; } } /** * @see org.wyona.yarep.core.Node#setMimeType(java.lang.String) */ public void setMimeType(String mimeType) throws RepositoryException { setProperty(PROPERTY_MIME_TYPE, mimeType); } /** * @see org.wyona.yarep.core.Node#getEncoding() */ public String getEncoding() throws RepositoryException { Property encoding = getProperty(PROPERTY_ENCODING); if (encoding != null) { return encoding.getString(); } else { return null; } } /** * @see org.wyona.yarep.core.Node#setEncoding(java.lang.String) */ public void setEncoding(String encoding) throws RepositoryException { setProperty(PROPERTY_ENCODING, encoding); } }