001 /*
002 * Copyright 2011 The Kuali Foundation.
003 *
004 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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 package org.kuali.ole.repository;
017
018 import org.apache.commons.io.FileUtils;
019 import org.kuali.ole.RepositoryManager;
020 import org.kuali.ole.docstore.DocStoreConstants;
021 import org.kuali.ole.docstore.OleDocStoreException;
022 import org.kuali.ole.docstore.model.enums.DocFormat;
023 import org.kuali.ole.docstore.model.enums.DocType;
024 import org.kuali.ole.docstore.model.xmlpojo.ingest.AdditionalAttributes;
025 import org.kuali.ole.docstore.model.xmlpojo.ingest.RequestDocument;
026 import org.kuali.ole.documenthandler.WorkBibMarcContentHandler;
027 import org.kuali.ole.documenthandler.WorkInstanceOleMLContentHandler;
028 import org.kuali.ole.pojo.OleException;
029 import org.slf4j.Logger;
030 import org.slf4j.LoggerFactory;
031
032 import javax.jcr.*;
033 import java.io.ByteArrayInputStream;
034 import java.io.File;
035 import java.io.InputStream;
036 import java.util.Calendar;
037 import java.util.Collection;
038 import java.util.Date;
039 import java.util.Iterator;
040 import java.text.DateFormat;
041 import java.text.SimpleDateFormat;
042
043 import static org.kuali.ole.docstore.process.ProcessParameters.*;
044
045 /**
046 * Created by IntelliJ IDEA.
047 * User: pvsubrah
048 * Date: 9/11/11
049 * Time: 10:37 AM
050 * To change this template use File | Settings | File Templates.
051 */
052 public class NodeHandler {
053
054 private static final Logger logger = LoggerFactory.getLogger(NodeHandler.class);
055
056 public Node initStaticNode(String nodeName, Node parentNode, Session session) throws RepositoryException {
057 Node node;
058 if (!parentNode.hasNode(nodeName)) {
059 synchronized (session) {
060 node = parentNode.addNode(nodeName, "nt:unstructured");
061 node.setProperty("nodeType", "folder");
062 node.addMixin("mix:referenceable");
063 session.save();
064 }
065 }
066 else {
067 node = parentNode.getNode(nodeName);
068 }
069 return node;
070 }
071
072 public Node initNonStaticNode(String nodeName, Node parentNode) throws RepositoryException {
073 Node node;
074 node = parentNode.addNode(nodeName, "nt:unstructured");
075 node.setProperty("nodeType", "folder");
076 node.addMixin("mix:referenceable");
077 return node;
078 }
079
080 public synchronized Node initFileNode(RequestDocument document, String name, Node parentNode, Session session)
081 throws Exception {
082 DocStoreConstants docStoreConstants = new DocStoreConstants();
083 String uuid = null;
084 Node fileNode = null;
085 try {
086 NodeIterator nodes = parentNode.getNodes(name);
087 if (nodes.getSize() >= BUCKET_SIZE_FILE_NODES) {
088 if (DocFormat.OLEML.isEqualTo(document.getFormat())) {
089 throw new RuntimeException("FileNode creation failed as the BUCKET_SIZE[" + BUCKET_SIZE_FILE_NODES
090 + "] is FULL: for the doc: " + document.getFormat() + "\n@ level: "
091 + parentNode.getPath() + "/" + name + "[" + (nodes.getSize() + 1) + "]");
092 }
093 else {
094 parentNode = initLevelNode(parentNode.getName(), parentNode.getParent(), true, session);
095 }
096 }
097
098 fileNode = parentNode.addNode(name, "olefile");
099 fileNode.addMixin("mix:referenceable");
100 if (DocType.LICENSE.isEqualTo(document.getType()) || docStoreConstants.isVersioningEnabled ) {
101 fileNode.addMixin("mix:versionable");
102 }
103
104 AdditionalAttributes additionalAttributes = document.getAdditionalAttributes();
105 if (DocType.LICENSE.isEqualTo(document.getType()) && !DocFormat.ONIXPL.isEqualTo(document.getFormat())) {
106 String docName = new File(document.getDocumentName()).getName();
107 additionalAttributes.setAttribute("dateLoaded", Calendar.getInstance().toString());
108 additionalAttributes.setAttribute("fileName", docName);
109 additionalAttributes.setAttribute("owner", document.getUser());
110 }
111
112 if (additionalAttributes != null) {
113 Collection<String> attributeNames = additionalAttributes.getAttributeNames();
114 if (attributeNames != null && attributeNames.size() > 0) {
115 for (Iterator<String> iterator = attributeNames.iterator(); iterator.hasNext(); ) {
116 String attributeName = iterator.next();
117 String attributeValue = additionalAttributes.getAttribute(attributeName);
118 fileNode.setProperty(attributeName, attributeValue);
119 }
120 }
121
122 }
123 else {
124 fileNode.setProperty("dateEntered", Calendar.getInstance());
125 fileNode.setProperty("lastUpdated", Calendar.getInstance());
126 }
127
128 Node resNode = fileNode.addNode("jcr:content", "nt:resource");
129 resNode.setProperty("jcr:mimeType", "application/xml");
130 resNode.setProperty("jcr:encoding", "");
131
132 String charset = "UTF-8";
133 byte[] documentBytes = null;
134 try {
135 uuid = fileNode.getIdentifier();
136 document.setUuid(uuid);
137 // Content Manipulations
138 if (DocFormat.MARC.isEqualTo(document.getFormat())) {
139 new WorkBibMarcContentHandler().doPreIngestContentManipulations(document, uuid);
140 }
141 else if (DocFormat.OLEML.isEqualTo(document.getFormat())) {
142 (new WorkInstanceOleMLContentHandler())
143 .doInstanceOleMLContentManipulations(document, uuid, parentNode);
144 }
145
146 if (document.getContent() != null && document.getContent().getContent() != null) {
147 documentBytes = document.getContent().getContent().getBytes();
148 }
149
150 else if (document.getDocumentName() != null) {
151 File file = new File(document.getDocumentName());
152 if (file.exists()) {
153 documentBytes = FileUtils.readFileToByteArray(file);
154 }
155 }
156 }
157 catch (Exception e) {
158 logger.error("Failed to convert document string to byte[] with charset " + charset, e);
159 }
160 InputStream docInputStream = new ByteArrayInputStream(documentBytes);
161 Binary binary = session.getValueFactory().createBinary(docInputStream);
162 resNode.setProperty("jcr:data", binary);
163 Calendar lastModified = Calendar.getInstance();
164 lastModified.setTimeInMillis(new Date().getTime());
165 resNode.setProperty("jcr:lastModified", lastModified);
166 logger.debug(fileNode.getPath() + " : " + uuid);
167 }
168 catch (RepositoryException e) {
169 logger.error("File Node Cannot be Created: " + e.getMessage(), e);
170 }
171 return fileNode;
172 }
173
174 /**
175 * Initializes the given fileNode with info from given requestDocument.
176 *
177 * @param fileNode
178 * @param document
179 * @param name
180 * @param parentNode
181 * @param session
182 * @return
183 * @throws Exception
184 */
185 public synchronized Node initFileNode(Node fileNode, RequestDocument document, String name, Node parentNode,
186 Session session) throws Exception {
187 String uuid = null;
188 //Node fileNode = null;
189 DocStoreConstants docStoreConstants = new DocStoreConstants();
190 try {
191 /*NodeIterator nodes = parentNode.getNodes(name);
192 if (nodes.getSize() >= BUCKET_SIZE_FILE_NODES) {
193 if (DocFormat.OLEML.isEqualTo(document.getFormat()))
194 throw new RuntimeException("FileNode creation failed as the BUCKET_SIZE[" + BUCKET_SIZE_FILE_NODES + "] is FULL: for the doc: "
195 + document.getFormat() + "\n@ level: " + parentNode.getPath() + "/" + name + "[" + (nodes.getSize() + 1) + "]");
196 else
197 parentNode = initLevelNode(parentNode.getName(), parentNode.getParent(), true, session);
198 }
199
200 fileNode = parentNode.addNode(name, "olefile"); */
201 DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS");
202 Date date = new Date();
203 //logger.info("NODE INIT: STARTING TIME \t" + dateFormat.format(date));
204 fileNode.addMixin("mix:referenceable");
205 if (DocType.LICENSE.isEqualTo(document.getType()) || docStoreConstants.isVersioningEnabled) {
206 fileNode.addMixin("mix:versionable");
207 }
208
209 AdditionalAttributes additionalAttributes = document.getAdditionalAttributes();
210 if (DocType.LICENSE.isEqualTo(document.getType()) && !DocFormat.ONIXPL.isEqualTo(document.getFormat())) {
211 String docName = new File(document.getDocumentName()).getName();
212 additionalAttributes.setAttribute("dateLoaded", Calendar.getInstance().toString());
213 additionalAttributes.setAttribute("fileName", docName);
214 additionalAttributes.setAttribute("owner", document.getUser());
215 }
216
217 if (additionalAttributes != null) {
218 Collection<String> attributeNames = additionalAttributes.getAttributeNames();
219 if (attributeNames != null && attributeNames.size() > 0) {
220 for (Iterator<String> iterator = attributeNames.iterator(); iterator.hasNext(); ) {
221 String attributeName = iterator.next();
222 String attributeValue = additionalAttributes.getAttribute(attributeName);
223 fileNode.setProperty(attributeName, attributeValue);
224 }
225 }
226
227 }
228 else {
229 fileNode.setProperty("dateEntered", Calendar.getInstance());
230 fileNode.setProperty("lastUpdated", Calendar.getInstance());
231 }
232
233 Node resNode = fileNode.addNode("jcr:content", "nt:resource");
234 resNode.setProperty("jcr:mimeType", "application/xml");
235 resNode.setProperty("jcr:encoding", "");
236
237 String charset = "UTF-8";
238 byte[] documentBytes = null;
239 try {
240 uuid = fileNode.getIdentifier();
241 document.setUuid(uuid);
242 // Content Manipulations
243 if (DocFormat.MARC.isEqualTo(document.getFormat())) {
244 new WorkBibMarcContentHandler().doPreIngestContentManipulations(document, uuid);
245 }
246 else if (DocFormat.OLEML.isEqualTo(document.getFormat())) {
247 (new WorkInstanceOleMLContentHandler())
248 .doInstanceOleMLContentManipulations(document, uuid, parentNode);
249 }
250
251 if (document.getContent() != null && document.getContent().getContent() != null) {
252 documentBytes = document.getContent().getContent().getBytes();
253 }
254 else if (document.getDocumentName() != null) {
255 File file = new File(document.getDocumentName());
256 if (file.exists()) {
257 documentBytes = FileUtils.readFileToByteArray(file);
258 }
259 }
260
261
262 }
263 catch (Exception e) {
264 logger.error("Failed to convert document string to byte[] with charset " + charset, e);
265 }
266 InputStream docInputStream = new ByteArrayInputStream(documentBytes);
267 Binary binary = session.getValueFactory().createBinary(docInputStream);
268 resNode.setProperty("jcr:data", binary);
269 Calendar lastModified = Calendar.getInstance();
270 lastModified.setTimeInMillis(new Date().getTime());
271 resNode.setProperty("jcr:lastModified", lastModified);
272 logger.debug(fileNode.getPath() + " : " + uuid);
273 //logger.info("NODE INIT: ENDING TIME \t" + dateFormat.format(date));
274 }
275 catch (RepositoryException e) {
276 logger.error("File Node Cannot be Created: " + e.getMessage(), e);
277 }
278
279 return fileNode;
280 }
281
282 public synchronized Node initLevelNode(String name, Node parent, boolean isRecursiveCall, Session session)
283 throws Exception {
284 long existing = 0;
285 try {
286 long bucketSize = BUCKET_SIZES.get(name);
287 boolean hasRepeatedChild = HAS_REPEATED_CHILD.get(name);
288 if (parent.hasNode(name)) {
289 NodeIterator existingNodes = parent.getNodes(name);
290 existing = existingNodes.getSize();
291 if (existing <= bucketSize && !((isRecursiveCall && existing == bucketSize) || (!hasRepeatedChild
292 && existing
293 == bucketSize))) {
294 if (hasRepeatedChild && !isRecursiveCall) {
295 existingNodes.skip(existing - 1);
296 return existingNodes.nextNode();
297 }
298 else {
299 Node levelNode = initNonStaticNode(name, parent);
300 if (existing == 0) {
301 session.save();
302 }
303 return levelNode;
304 }
305 }
306 else {
307 if (!STATIC_NODES.contains(parent.getPath())) {
308 parent = initLevelNode(parent.getName(), parent.getParent(), true, session);
309 return initNonStaticNode(name, parent);
310 }
311 else {
312 throw new Exception("Node [" + parent.getName() + "/" + name + "[" + (existing + 1)
313 + "]] Cannot Be Created. CAUSE: TREE [" + bucketSize + "] FULL ");
314 }
315 }
316 }
317 else {
318 return initNonStaticNode(name, parent);
319 }
320 }
321 catch (Exception e) {
322 try {
323 logger.error(
324 "Exception While initializing Node: " + parent.getName() + "/" + name + "[" + (existing + 1)
325 + "] \t to Parent: " + parent.getName(), e);
326 }
327 catch (RepositoryException e1) {
328 }
329 throw e;
330 }
331 }
332
333 public Node getNodeByUUID(Session session, String uuid) throws OleException {
334 logger.debug("Started getting node for UUID:" + uuid);
335 boolean isNewSession = false;
336 if (null == session) {
337 isNewSession = true;
338 logger.debug("Initilalizing new session");
339 session = RepositoryManager.getRepositoryManager().getSession("nodeHandler", "getNodeByUUID");
340 }
341 try {
342 return session.getNodeByIdentifier(uuid);
343 }
344 catch (RepositoryException e) {
345 throw new OleException("getNodeByUUID failed", e);
346 }
347 finally {
348 if (isNewSession) {
349 RepositoryManager.getRepositoryManager().logout(session);
350 }
351 }
352 }
353
354 }