/* * #%L * Alfresco Remote API * %% * Copyright (C) 2005 - 2016 Alfresco Software Limited * %% * This file is part of the Alfresco software. * If the software was purchased under a paid Alfresco license, the terms of * the paid license agreement will prevail. Otherwise, the software is * provided under the following open source license terms: * * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . * #L% */ package org.alfresco.rest.api.model; import java.io.Serializable; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.rest.framework.resource.UniqueId; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.NoSuchPersonException; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.namespace.QName; import org.alfresco.util.EqualsHelper; import org.apache.chemistry.opencmis.commons.data.PropertyData; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Concrete class carrying general information for alf_node data * * @author steveglover * @author Gethin James * @author janv */ public class Node implements Comparable { private static final Log logger = LogFactory.getLog(Node.class); protected NodeRef nodeRef; protected String name; protected Date createdAt; protected Date modifiedAt; protected UserInfo createdByUser; protected UserInfo modifiedByUser; // Archived info - specifically for archive (deleted) node - see Trashcan API protected Date archivedAt; protected UserInfo archivedByUser; // Version info - specifically for version node - see Version History API protected String versionComment; protected Boolean isFolder; protected Boolean isFile; protected Boolean isLink; protected Boolean isLocked; protected NodeRef parentNodeRef; protected PathInfo pathInfo; protected String prefixTypeQName; // please note: these are currently only used (optionally) for node create request protected String relativePath; protected List secondaryChildren; protected List targets; protected List aspectNames; protected Map properties; protected List allowableOperations; public Node(NodeRef nodeRef, NodeRef parentNodeRef, Map nodeProps, Map mapUserInfo, ServiceRegistry sr) { if(nodeRef == null) { throw new IllegalArgumentException(); } this.nodeRef = nodeRef; this.parentNodeRef = parentNodeRef; mapMinimalInfo(nodeProps, mapUserInfo, sr); } protected Object getValue(Map> props, String name) { PropertyData prop = props.get(name); Object value = (prop != null ? prop.getFirstValue() : null); return value; } public Node() { } protected void mapMinimalInfo(Map nodeProps, Map mapUserInfo, ServiceRegistry sr) { PersonService personService = sr.getPersonService(); this.name = (String)nodeProps.get(ContentModel.PROP_NAME); if (mapUserInfo == null) { // minor: save one lookup if creator & modifier are the same mapUserInfo = new HashMap<>(2); } this.createdAt = (Date)nodeProps.get(ContentModel.PROP_CREATED); this.createdByUser = lookupUserInfo((String)nodeProps.get(ContentModel.PROP_CREATOR), mapUserInfo, personService); this.modifiedAt = (Date)nodeProps.get(ContentModel.PROP_MODIFIED); this.modifiedByUser = lookupUserInfo((String)nodeProps.get(ContentModel.PROP_MODIFIER), mapUserInfo, personService); } public static UserInfo lookupUserInfo(String userName, Map mapUserInfo, PersonService personService) { return lookupUserInfo(userName, mapUserInfo, personService, false); } public static UserInfo lookupUserInfo(String userName, Map mapUserInfo, PersonService personService, boolean displayNameOnly) { UserInfo userInfo = mapUserInfo.get(userName); if ((userInfo == null) && (userName != null)) { String sysUserName = AuthenticationUtil.getSystemUserName(); if (userName.equals(sysUserName) || (AuthenticationUtil.isMtEnabled() && userName.startsWith(sysUserName + "@"))) { userInfo = new UserInfo((displayNameOnly ? null : userName), userName, ""); } else { PersonService.PersonInfo pInfo = null; try { NodeRef pNodeRef = personService.getPerson(userName, false); if (pNodeRef != null) { pInfo = personService.getPerson(pNodeRef); } } catch (NoSuchPersonException nspe) { // drop-through } if (pInfo != null) { userInfo = new UserInfo((displayNameOnly ? null : userName), pInfo.getFirstName(), pInfo.getLastName()); } else { logger.warn("Unknown person: "+userName); userInfo = new UserInfo((displayNameOnly ? null : userName), userName, ""); } } mapUserInfo.put(userName, userInfo); } return userInfo; } // note: nodeRef maps to json "id" (when serializing/deserializng) @UniqueId public NodeRef getNodeRef() { return nodeRef; } public void setNodeRef(NodeRef nodeRef) { this.nodeRef = nodeRef; } public Date getCreatedAt() { return this.createdAt; } public void setCreated(Date createdAt) { this.createdAt = createdAt; } public Date getModifiedAt() { return modifiedAt; } public UserInfo getModifiedByUser() { return modifiedByUser; } public UserInfo getCreatedByUser() { return createdByUser; } public void setCreatedByUser(UserInfo createdByUser) { this.createdByUser = createdByUser; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public PathInfo getPath() { return pathInfo; } public void setPath(PathInfo pathInfo) { this.pathInfo = pathInfo; } public String getNodeType() { return prefixTypeQName; } public void setNodeType(String prefixType) { this.prefixTypeQName = prefixType; } public Map getProperties() { return this.properties; } public void setProperties(Map props) { this.properties = props; } public List getAspectNames() { return aspectNames; } public void setAspectNames(List aspectNames) { this.aspectNames = aspectNames; } public NodeRef getParentId() { return parentNodeRef; } public void setParentId(NodeRef parentNodeRef) { this.parentNodeRef = parentNodeRef; } public Boolean getIsFolder() { return isFolder; } public void setIsFolder(Boolean isFolder) { this.isFolder = isFolder; } public Boolean getIsFile() { return isFile; } public void setIsFile(Boolean isFile) { this.isFile = isFile; } public Boolean getIsLink() { return isLink; } public void setIsLink(Boolean isLink) { this.isLink = isLink; } public Boolean getIsLocked() { return isLocked; } public void setIsLocked(Boolean isLocked) { this.isLocked = isLocked; } public List getAllowableOperations() { return allowableOperations; } public void setAllowableOperations(List allowableOperations) { this.allowableOperations = allowableOperations; } public List getTargets() { return targets; } public void setTargets(List targets) { this.targets = targets; } public Date getArchivedAt() { return archivedAt; } public void setArchivedAt(Date archivedAt) { this.archivedAt = archivedAt; } public UserInfo getArchivedByUser() { return archivedByUser; } public void setArchivedByUser(UserInfo archivedByUser) { this.archivedByUser = archivedByUser; } public String getVersionComment() { return versionComment; } public void setVersionComment(String versionComment) { this.versionComment = versionComment; } public boolean equals(Object other) { if(this == other) { return true; } if(!(other instanceof Node)) { return false; } Node node = (Node)other; return EqualsHelper.nullSafeEquals(getNodeRef(), node.getNodeRef()); } public String getRelativePath() { return relativePath; } public void setRelativePath(String relativePath) { this.relativePath = relativePath; } public List getSecondaryChildren() { return secondaryChildren; } public void setSecondaryChildren(List secondaryChildren) { this.secondaryChildren = secondaryChildren; } @Override public int compareTo(Node node) { return getNodeRef().toString().compareTo(node.getNodeRef().toString()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Node [id=").append(getNodeRef().getId()); sb.append(", parentId=").append(getParentId()); sb.append(", type=").append(getNodeType()); sb.append(", name=").append(getName()); sb.append(", isFolder=").append(getIsFolder()); sb.append(", isFile=").append(getIsFile()); sb.append(", modifiedAt=").append(getModifiedAt()); sb.append(", modifiedByUser=").append(getModifiedByUser()); sb.append(", createdAt=").append(getCreatedAt()); sb.append(", createdByUser=").append(getCreatedByUser()); if (getArchivedAt() != null) { sb.append(", archivedAt=").append(getArchivedAt()); } if (getArchivedByUser() != null) { sb.append(", archivedByUser=").append(getArchivedByUser()); } if (getIsLink() != null) { sb.append(", isLink=").append(getIsLink()); // note: symbolic link (not shared link) } if (getPath() != null) { sb.append(", path=").append(getPath()); } if (getContent() != null) { sb.append(", content=").append(getContent()); } if (getAspectNames() != null) { sb.append(", aspectNames=").append(getAspectNames()); } if (getProperties() != null) { //sb.append(", properties=").append(getProperties()); } if (getRelativePath() != null) { sb.append(", relativePath=").append(getRelativePath()); } if (getAllowableOperations() != null) { sb.append(", allowableOperations=").append(getAllowableOperations()); } sb.append("]"); return sb.toString(); } // here to allow POST /nodes/{id}/children when creating empty file with specified content.mimeType // also allows list of results to be returned as "nodes" protected ContentInfo contentInfo; public void setContent(ContentInfo contentInfo) { this.contentInfo = contentInfo; } public ContentInfo getContent() { return this.contentInfo; } // when appropriate, can be used to show association (in the context of a listing), for example // GET /nodes/parentId/children, /nodes/parentId/secondary-children, /nodes/childId/parents // GET /nodes/sourceId/targets, /nodes/targetId/sources protected Assoc association; public Assoc getAssociation() { return association; } public void setAssociation(Assoc association) { this.association = association; } // TODO for backwards compat' - set explicitly when needed (ie. favourites) (note: we could choose to have separate old Node/NodeImpl etc) protected String title; protected NodeRef guid; protected String description; protected String createdBy; protected String modifiedBy; /** * @deprecated */ public NodeRef getGuid() { return guid; } /** * @deprecated */ public void setGuid(NodeRef guid) { this.guid = guid; } /** * @deprecated */ public String getTitle() { return title; } /** * @deprecated */ public void setTitle(String title) { this.title = title; } /** * @deprecated */ public String getDescription() { return description; } /** * @deprecated */ public void setDescription(String description) { this.description = description; } /** * @deprecated */ public String getCreatedBy() { return this.createdBy; } /** * @deprecated */ public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } /** * @deprecated */ public String getModifiedBy() { return modifiedBy; } /** * @deprecated */ public void setModifiedBy(String modifiedBy) { this.modifiedBy = modifiedBy; } }