001/* 002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Vladimir Pasquier <vpasquier@nuxeo.com> 016 */ 017package org.nuxeo.box.api.adapter; 018 019import org.nuxeo.box.api.marshalling.dao.BoxCollection; 020import org.nuxeo.box.api.marshalling.dao.BoxFile; 021import org.nuxeo.box.api.marshalling.dao.BoxFolder; 022import org.nuxeo.box.api.marshalling.dao.BoxItem; 023import org.nuxeo.box.api.marshalling.dao.BoxTypedObject; 024import org.nuxeo.box.api.marshalling.dao.BoxUser; 025import org.nuxeo.box.api.marshalling.exceptions.BoxJSONException; 026import org.nuxeo.box.api.service.BoxService; 027import org.joda.time.DateTime; 028import org.joda.time.format.ISODateTimeFormat; 029import org.nuxeo.ecm.core.api.CoreSession; 030import org.nuxeo.ecm.core.api.DocumentModel; 031import org.nuxeo.ecm.core.api.IdRef; 032import org.nuxeo.ecm.core.api.NuxeoPrincipal; 033import org.nuxeo.ecm.platform.tag.Tag; 034import org.nuxeo.ecm.platform.tag.TagService; 035import org.nuxeo.ecm.platform.usermanager.UserManager; 036import org.nuxeo.ecm.quota.size.QuotaAware; 037import org.nuxeo.ecm.quota.size.QuotaAwareDocument; 038import org.nuxeo.runtime.api.Framework; 039 040import java.lang.reflect.InvocationTargetException; 041import java.text.ParseException; 042import java.util.ArrayList; 043import java.util.Collections; 044import java.util.HashMap; 045import java.util.List; 046import java.util.Map; 047 048/** 049 * Abstract Box Adapter 050 * 051 * @since 5.9.2 052 */ 053public abstract class BoxAdapter { 054 055 protected final DocumentModel doc; 056 057 protected final Map<String, Object> boxProperties = new HashMap<>(); 058 059 protected BoxItem boxItem; 060 061 protected final BoxService boxService = Framework.getLocalService(BoxService.class); 062 063 public BoxAdapter(DocumentModel doc) { 064 this.doc = doc; 065 CoreSession session = doc.getCoreSession(); 066 067 boxProperties.put(BoxItem.FIELD_ID, boxService.getBoxId(doc)); 068 boxProperties.put(BoxItem.FIELD_SEQUENCE_ID, boxService.getBoxSequenceId(doc)); 069 boxProperties.put(BoxItem.FIELD_ETAG, boxService.getBoxEtag(doc)); 070 071 boxProperties.put(BoxItem.FIELD_NAME, doc.getName()); 072 boxProperties.put(BoxItem.FIELD_CREATED_AT, 073 ISODateTimeFormat.dateTime().print(new DateTime(doc.getPropertyValue("dc:created")))); 074 boxProperties.put(BoxItem.FIELD_MODIFIED_AT, 075 ISODateTimeFormat.dateTime().print(new DateTime(doc.getPropertyValue("dc:modified")))); 076 boxProperties.put(BoxItem.FIELD_DESCRIPTION, doc.getPropertyValue("dc:description")); 077 078 // size 079 QuotaAwareDocument quotaAwareDocument = null; 080 if (Framework.getRuntime().getBundle("org.nuxeo.ecm.quota.core") != null) { 081 quotaAwareDocument = (QuotaAwareDocument) doc.getAdapter(QuotaAware.class); 082 } 083 boxProperties.put(BoxItem.FIELD_SIZE, quotaAwareDocument != null ? quotaAwareDocument.getInnerSize() : -1.0); 084 085 // path_collection 086 final DocumentModel parentDoc = session.getParentDocument(doc.getRef()); 087 final Map<String, Object> pathCollection = new HashMap<>(); 088 List<BoxTypedObject> hierarchy = getParentsHierarchy(session, parentDoc); 089 pathCollection.put(BoxCollection.FIELD_ENTRIES, hierarchy); 090 pathCollection.put(BoxCollection.FIELD_TOTAL_COUNT, hierarchy.size()); 091 BoxCollection boxPathCollection = new BoxCollection(Collections.unmodifiableMap(pathCollection)); 092 boxProperties.put(BoxItem.FIELD_PATH_COLLECTION, boxPathCollection); 093 094 // parent 095 final Map<String, Object> parentProperties = new HashMap<>(); 096 parentProperties.put(BoxItem.FIELD_ID, boxService.getBoxId(parentDoc)); 097 parentProperties.put(BoxItem.FIELD_SEQUENCE_ID, boxService.getBoxSequenceId(parentDoc)); 098 parentProperties.put(BoxItem.FIELD_NAME, boxService.getBoxName(parentDoc)); 099 parentProperties.put(BoxItem.FIELD_ETAG, boxService.getBoxEtag(parentDoc)); 100 BoxFolder parentFolder = new BoxFolder(Collections.unmodifiableMap(parentProperties)); 101 boxProperties.put(BoxItem.FIELD_PARENT, parentFolder); 102 103 // Users 104 // Creator 105 final UserManager userManager = Framework.getLocalService(UserManager.class); 106 String creator = doc.getPropertyValue("dc:creator") != null ? (String) doc.getPropertyValue("dc:creator") 107 : "system"; 108 NuxeoPrincipal principalCreator = userManager.getPrincipal(creator); 109 final BoxUser boxCreator = boxService.fillUser(principalCreator); 110 boxProperties.put(BoxItem.FIELD_CREATED_BY, boxCreator); 111 112 // Last Contributor 113 String lastContributor = doc.getPropertyValue("dc:lastContributor") != null ? (String) doc.getPropertyValue("dc:lastContributor") 114 : "system"; 115 final NuxeoPrincipal principalLastContributor = userManager.getPrincipal(lastContributor); 116 final BoxUser boxContributor = boxService.fillUser(principalLastContributor); 117 boxProperties.put(BoxItem.FIELD_MODIFIED_BY, boxContributor); 118 119 // Owner 120 boxProperties.put(BoxItem.FIELD_OWNED_BY, boxCreator); 121 122 // Shared Link 123 boxProperties.put(BoxItem.FIELD_SHARED_LINK, null); 124 125 // Status 126 boxProperties.put(BoxItem.FIELD_ITEM_STATUS, doc.getCurrentLifeCycleState()); 127 128 // Tags 129 boxProperties.put(BoxItem.FIELD_TAGS, getTags(session)); 130 131 } 132 133 public BoxItem getBoxItem() { 134 return boxItem; 135 } 136 137 abstract public BoxItem getMiniItem(); 138 139 /** 140 * Update the box item properties 141 * 142 * @param boxItem containing values updated 143 */ 144 public void setBoxItem(BoxItem boxItem) { 145 for (String field : boxItem.getKeySet()) { 146 this.boxItem.put(field, boxItem.getValue(field)); 147 } 148 } 149 150 public DocumentModel getDoc() { 151 return doc; 152 } 153 154 protected List<BoxTypedObject> getParentsHierarchy(CoreSession session, DocumentModel parentDoc) 155 { 156 final List<BoxTypedObject> pathCollection = new ArrayList<>(); 157 while (parentDoc != null) { 158 final Map<String, Object> parentCollectionProperties = new HashMap<>(); 159 parentCollectionProperties.put(BoxItem.FIELD_ID, boxService.getBoxId(parentDoc)); 160 parentCollectionProperties.put(BoxItem.FIELD_SEQUENCE_ID, boxService.getBoxSequenceId(parentDoc)); 161 parentCollectionProperties.put(BoxItem.FIELD_ETAG, boxService.getBoxEtag(parentDoc)); 162 parentCollectionProperties.put(BoxItem.FIELD_NAME, boxService.getBoxName(parentDoc)); 163 BoxTypedObject boxParent; 164 // This different instantiation is related to the param type 165 // which is automatically added in json payload by Box marshaller 166 // following the box object type 167 if (parentDoc.isFolder()) { 168 boxParent = new BoxFolder(Collections.unmodifiableMap(parentCollectionProperties)); 169 } else { 170 boxParent = new BoxFile(Collections.unmodifiableMap(parentCollectionProperties)); 171 } 172 pathCollection.add(boxParent); 173 parentDoc = session.getParentDocument(parentDoc.getRef()); 174 } 175 return pathCollection; 176 } 177 178 protected String[] getTags(CoreSession session) { 179 final TagService tagService = Framework.getLocalService(TagService.class); 180 final List<Tag> tags = tagService.getDocumentTags(session, doc.getId(), session.getPrincipal().getName()); 181 final String[] tagNames = new String[tags.size()]; 182 int index = 0; 183 for (Tag tag : tags) { 184 tagNames[index] = tag.getLabel(); 185 index++; 186 } 187 return tagNames; 188 } 189 190 /** 191 * Update the document (nx/box sides) thanks to a box item 192 */ 193 public void save(CoreSession session) throws ParseException, InvocationTargetException, 194 IllegalAccessException, BoxJSONException { 195 196 setDescription(boxItem.getDescription()); 197 setCreator(boxItem.getOwnedBy().getId()); 198 199 String id = boxItem.getParent().getId(); 200 // check if id is root's one 201 String newParentId = "0".equals(id) ? session.getRootDocument().getId() : id; 202 IdRef documentIdRef = new IdRef(doc.getId()); 203 204 // If the name has changed, update location in Nuxeo repository 205 // OR if parent id has been updated -> move the document 206 String oldParentId = session.getParentDocument(documentIdRef).getId(); 207 if (!oldParentId.equals(newParentId) || !doc.getName().equals(boxItem.getName())) { 208 209 session.move(documentIdRef, new IdRef(newParentId), boxItem.getName()); 210 // Title and name are same here 211 setTitle(boxItem.getName()); 212 } 213 214 // Tags 215 TagService tagService = Framework.getLocalService(TagService.class); 216 if (tagService != null) { 217 if (boxItem.getTags().length != 0) { 218 tagService.removeTags(session, doc.getId()); 219 for (String tag : boxItem.getTags()) { 220 tagService.tag(session, doc.getId(), tag, session.getPrincipal().getName()); 221 } 222 } 223 } 224 session.saveDocument(doc); 225 session.save(); 226 } 227 228 public void setTitle(String value) { 229 doc.setPropertyValue("dc:title", value); 230 } 231 232 public void setDescription(String value) { 233 doc.setPropertyValue("dc:description", value); 234 } 235 236 public void setCreator(String value) { 237 doc.setPropertyValue("dc:creator", value); 238 } 239}