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