001package org.kuali.ole.docstore.document.jcr;
002
003import org.apache.commons.lang.StringUtils;
004import org.kuali.ole.docstore.OleDocStoreException;
005import org.kuali.ole.docstore.common.document.content.instance.CallNumber;
006import org.kuali.ole.docstore.common.document.content.instance.Item;
007import org.kuali.ole.docstore.common.document.content.instance.OleHoldings;
008import org.kuali.ole.docstore.common.document.content.instance.xstream.HoldingOlemlRecordProcessor;
009import org.kuali.ole.docstore.discovery.service.QueryServiceImpl;
010import org.kuali.ole.docstore.document.DocumentManager;
011import org.kuali.ole.docstore.model.enums.DocCategory;
012import org.kuali.ole.docstore.model.enums.DocFormat;
013import org.kuali.ole.docstore.model.enums.DocType;
014import org.kuali.ole.docstore.model.xmlpojo.ingest.Content;
015import org.kuali.ole.docstore.model.xmlpojo.ingest.RequestDocument;
016import org.kuali.ole.docstore.model.xmlpojo.ingest.ResponseDocument;
017import org.kuali.ole.docstore.common.document.content.instance.ShelvingScheme;
018import org.kuali.ole.docstore.common.document.content.instance.xstream.ItemOlemlRecordProcessor;
019import org.kuali.ole.docstore.process.ProcessParameters;
020import org.kuali.ole.docstore.service.BeanLocator;
021import org.slf4j.Logger;
022import org.slf4j.LoggerFactory;
023
024import javax.jcr.Node;
025import javax.jcr.RepositoryException;
026import javax.jcr.Session;
027import java.io.FileNotFoundException;
028import java.util.ArrayList;
029import java.util.Iterator;
030import java.util.List;
031
032import static org.kuali.ole.docstore.process.ProcessParameters.FILE_HOLDINGS;
033
034/**
035 * Created with IntelliJ IDEA.
036 * User: SG7940
037 * Date: 1/23/13
038 * Time: 5:09 PM
039 * To change this template use File | Settings | File Templates.
040 */
041public class JcrWorkItemDocumentManager extends JcrWorkInstanceDocumentManager {
042
043    private static JcrWorkItemDocumentManager ourInstance = null;
044    private static Logger LOG = LoggerFactory.getLogger(JcrWorkItemDocumentManager.class);
045
046    public static JcrWorkItemDocumentManager getInstance() {
047        if (null == ourInstance) {
048            ourInstance = new JcrWorkItemDocumentManager();
049        }
050        return ourInstance;
051    }
052
053
054    @Override
055    public List<ResponseDocument> deleteVerify(List<RequestDocument> requestDocument, Object object) {
056        return null;
057    }
058
059    @Override
060    public ResponseDocument deleteVerify(RequestDocument requestDocument, Object object) throws Exception {
061        Session session = (Session) object;
062        LOG.debug("workItemDocumentManager deleteVerify method");
063        List<String> instanceIdentifierList = new ArrayList<String>();
064        ResponseDocument responseDocument = new ResponseDocument();
065        List<String> itemIdentifierList = new ArrayList<String>();
066        itemIdentifierList.add(requestDocument.getUuid());
067        boolean exists = checkInstancesOrItemsExistsInOLE(itemIdentifierList);
068        if (exists) {
069            responseDocument.setId(requestDocument.getId());
070            responseDocument.setCategory(requestDocument.getCategory());
071            responseDocument.setType(requestDocument.getType());
072            responseDocument.setFormat(requestDocument.getFormat());
073            responseDocument.setUuid(requestDocument.getUuid());
074            responseDocument.setStatus("failure'");
075            responseDocument.setStatusMessage("Instances or Items in use. So deletion cannot be done");
076            return responseDocument;
077        }
078        Node itemNode = session.getNodeByIdentifier(requestDocument.getUuid());
079
080        long itemSize = itemNode.getParent().getNodes().getSize() - 2;
081        LOG.debug("JcrWorkItemDocumentManager : itemSize " + itemSize);
082        String instanceIdentifier = itemNode.getParent().getParent().getIdentifier();
083        LOG.debug("JcrWorkItemDocumentManager : instanceIdentifier " + instanceIdentifier);
084/*         if(itemSize==1){
085            requestDocument.setUuid(instanceIdentifier);
086            requestDocument.setCategory(DocCategory.WORK.getCode());
087            requestDocument.setType(DocType.INSTANCE.getCode());
088            requestDocument.setFormat(DocFormat.OLEML.getCode());
089            responseDocument = JcrWorkInstanceDocumentManager.getInstance().deleteVerify(requestDocument, session);
090        }
091        else{*/
092        responseDocument.setUuid(requestDocument.getUuid());
093        responseDocument.setId(requestDocument.getId());
094        responseDocument.setCategory(requestDocument.getCategory());
095        responseDocument.setType(requestDocument.getType());
096        responseDocument.setFormat(requestDocument.getFormat());
097        responseDocument.setStatus("success");
098        responseDocument.setStatusMessage("success");
099        // }
100        return responseDocument;
101    }
102
103    @Override
104    public ResponseDocument delete(RequestDocument requestDocument, Object object) throws Exception {
105        Session session = (Session) object;
106        LOG.debug("in JcrWorkItemDocumentManager :delete");
107        DocumentManager documentManager = null;
108        ResponseDocument responseDocument = new ResponseDocument();
109        ResponseDocument responseDocumentFromDeleteVerify = deleteVerify(requestDocument, session);
110        LOG.debug("in JcrWorkItemDocumentManager :delete after verify getUuid " + responseDocumentFromDeleteVerify.getUuid());
111        String status = responseDocumentFromDeleteVerify.getStatus();
112        LOG.debug("in JcrWorkItemDocumentManager :delete status " + status);
113
114        if (status.equalsIgnoreCase("success")) {
115            if (responseDocumentFromDeleteVerify.getCategory().equalsIgnoreCase("work") && responseDocumentFromDeleteVerify.getFormat().equalsIgnoreCase("oleml") && responseDocumentFromDeleteVerify.getType().equalsIgnoreCase("instance")) {
116                LOG.debug("in JcrWorkItemDocumentManager :delete if of instance");
117                RequestDocument requestDocumentForInstance = prepareRequestDocument(responseDocumentFromDeleteVerify);
118                documentManager = BeanLocator.getDocstoreFactory().getDocumentManager(requestDocumentForInstance.getCategory(), requestDocumentForInstance.getType(), requestDocumentForInstance.getFormat());
119                responseDocument = documentManager.delete(requestDocumentForInstance, session);
120            } else if (responseDocumentFromDeleteVerify.getCategory().equalsIgnoreCase("work") && responseDocumentFromDeleteVerify.getFormat().equalsIgnoreCase("marc") && responseDocumentFromDeleteVerify.getType().equalsIgnoreCase("bibliographic")) {
121                LOG.debug("in JcrWorkItemDocumentManager :delete if of marc");
122                RequestDocument requestDocumentForBib = prepareRequestDocument(responseDocumentFromDeleteVerify);
123                documentManager = BeanLocator.getDocstoreFactory().getDocumentManager(requestDocumentForBib.getCategory(), requestDocumentForBib.getType(), requestDocument.getFormat());
124                responseDocument = documentManager.delete(requestDocumentForBib, session);
125            } else if (responseDocumentFromDeleteVerify.getCategory().equalsIgnoreCase("work") && responseDocumentFromDeleteVerify.getFormat().equalsIgnoreCase("oleml") && responseDocumentFromDeleteVerify.getType().equalsIgnoreCase("item")) {
126                LOG.debug("in JcrWorkItemDocumentManager :delete if of item");
127                List<String> itemIdentifierList = new ArrayList<String>();
128                itemIdentifierList.add(requestDocument.getUuid());
129                deleteFromRepository(itemIdentifierList, session);
130
131            }
132        }
133        return responseDocument;
134    }
135
136    @Override
137    protected void modifyContent(RequestDocument reqDoc, Session session, Node nodeByUUID)
138            throws RepositoryException, FileNotFoundException, OleDocStoreException {
139        if (reqDoc.getOperation().equalsIgnoreCase("checkIn")) {
140            ItemOlemlRecordProcessor itemProcessor = new ItemOlemlRecordProcessor();
141
142            if (reqDoc.getContent() != null && reqDoc.getContent().getContent() != null) {
143                // get new item content to check in
144                Item newItem = itemProcessor.fromXML(reqDoc.getContent().getContent());
145                // verify new item call number and shelving scheme to build sortable call num
146                Boolean status = true;
147                if (newItem.getCallNumber() == null) {
148                    newItem.setCallNumber(new CallNumber());
149                }
150                CallNumber cNum = newItem.getCallNumber();
151                if (!(cNum.getShelvingOrder() != null && cNum.getShelvingOrder().getFullValue() != null &&
152                        cNum.getShelvingOrder().getFullValue().trim().length() > 0)) {
153                    if (!(cNum.getNumber() != null && cNum.getNumber().trim().length() > 0)) {
154                        OleHoldings hold = getHoldings(nodeByUUID);
155                        updateShelvingOrder(newItem, hold);
156                        status = false;
157                    } else {
158                        updateShelvingOrder(newItem, null);
159                        status = false;
160                    }
161                }
162                if (status) {
163                    //get already existing item content from jcr.
164                    String existingItemXml = nodeManager.getData(nodeByUUID);
165                    // if new item contains shelving scheme and call number
166                    if (existingItemXml != null) {
167                        Item existItem = itemProcessor.fromXML(existingItemXml);
168                        if (existItem.getCallNumber() == null) {
169                            existItem.setCallNumber(new CallNumber());
170                        }
171                        CallNumber existCNum = existItem.getCallNumber();
172                        setItemValuesFromNullToEmpty(existItem);
173                        setItemValuesFromNullToEmpty(newItem);
174                        cNum = newItem.getCallNumber();
175                        computeCallNumberType(cNum);
176                        if (!(existCNum.getNumber().equalsIgnoreCase((cNum.getNumber()))) |
177                                !(existCNum.getShelvingScheme().getCodeValue().equalsIgnoreCase(cNum.getShelvingScheme().getCodeValue())) |
178                                !((existItem.getEnumeration()).equalsIgnoreCase(newItem.getEnumeration())) |
179                                !((existItem.getChronology()).equalsIgnoreCase(newItem.getChronology())) |
180                                !((existItem.getCopyNumber()).equalsIgnoreCase(newItem.getCopyNumber()))) {
181                            if (!(cNum.getNumber() != null && cNum.getNumber().trim().length() > 0)) {
182                                OleHoldings hold = getHoldings(nodeByUUID);
183                                updateShelvingOrder(newItem, hold);
184                            } else {
185                                updateShelvingOrder(newItem, null);
186                            }
187
188                        }
189                    }
190                }
191                reqDoc.getContent().setContent(itemProcessor.toXML(newItem));
192            }
193        }
194    }
195
196    private OleHoldings getHoldings(Node nodeByUUID) throws RepositoryException, FileNotFoundException, OleDocStoreException {
197        // if new item call num and shelving scheme are empty get them from holdings.
198        Node holdingsNode = nodeByUUID.getParent();
199        Node holdingsFileNode = holdingsNode.getNode(FILE_HOLDINGS);
200        String holdXml = nodeManager.getData(holdingsFileNode);
201        HoldingOlemlRecordProcessor holdProc = new HoldingOlemlRecordProcessor();
202        OleHoldings hold = holdProc.fromXML(holdXml);
203        return hold;
204    }
205
206    protected void updateItemCallNumberFromHoldings(Node nodeByUUID, OleHoldings newHold, RequestDocument reqDoc)
207            throws RepositoryException, FileNotFoundException, OleDocStoreException {
208        Node holdingsNode = nodeByUUID.getParent();
209//        Node itemNode = holdingsNode.getNodes(ProcessParameters.FILE_ITEM);
210        for (Iterator<Node> itemIterator = holdingsNode.getNodes(ProcessParameters.FILE_ITEM); itemIterator.hasNext(); ) {
211            Node itemNode = itemIterator.next();
212            String itemXml = nodeManager.getData(itemNode);
213            String uuid = itemNode.getProperty("jcr:uuid").getString();
214            ItemOlemlRecordProcessor itemProcessor = new ItemOlemlRecordProcessor();
215            Item item = itemProcessor.fromXML(itemXml);
216            if (item != null) {
217                if (item.getCallNumber() == null) {
218                    item.setCallNumber(new CallNumber());
219                }
220                item.getCallNumber().setNumber("");
221                if (item.getCallNumber().getShelvingScheme() != null)
222                    item.getCallNumber().getShelvingScheme().setCodeValue("");
223                updateShelvingOrder(item, newHold);
224                String newItemXml = itemProcessor.toXML(item);
225                buildRequestDocumentForItem(newItemXml, reqDoc, uuid);
226            }
227        }
228    }
229
230    protected void updateContentToNode(RequestDocument reqDoc, Session session, byte[] documentBytes, Node nodeByUUID)
231            throws RepositoryException, OleDocStoreException {
232        documentBytes = convertContentToBytes(reqDoc);
233        super.updateContentToNode(reqDoc, session, documentBytes, nodeByUUID);
234    }
235
236    private void buildRequestDocumentForItem(String newItemXml, RequestDocument reqDoc, String uuid) {
237        RequestDocument requestDocument = new RequestDocument();
238        requestDocument.setOperation("checkIn");
239        requestDocument.setCategory(DocCategory.WORK.getCode());
240        requestDocument.setType(DocType.ITEM.getCode());
241        requestDocument.setFormat(DocFormat.OLEML.getCode());
242        requestDocument.setUuid(uuid);
243        requestDocument.setId(uuid);
244        Content content = new Content();
245        content.setContent(newItemXml);
246        requestDocument.setContent(content);
247        List<RequestDocument> reqDocList = reqDoc.getLinkedRequestDocuments();
248        if (reqDocList == null) {
249            reqDoc.setLinkedRequestDocuments(new ArrayList<RequestDocument>());
250        }
251        reqDocList.add(requestDocument);
252    }
253
254    private void setItemValuesFromNullToEmpty(Item item) {
255        CallNumber existCNum = item.getCallNumber();
256        if (existCNum == null) {
257            item.setCallNumber(new CallNumber());
258        }
259        if (existCNum.getNumber() == null) {
260            existCNum.setNumber("");
261        }
262        ShelvingScheme existSS = existCNum.getShelvingScheme();
263        if (existSS == null) {
264            existCNum.setShelvingScheme(new ShelvingScheme());
265            existSS = existCNum.getShelvingScheme();
266        }
267        if (existSS != null && !(existSS.getCodeValue() != null && existSS.getCodeValue().trim().length() > 0)) {
268            existSS.setCodeValue("");
269        }
270        if (item.getEnumeration() == null) {
271            item.setEnumeration("");
272        }
273        if (item.getChronology() == null) {
274            item.setChronology("");
275        }
276        if (item.getCopyNumber() == null) {
277            item.setCopyNumber("");
278        }
279    }
280
281    @Override
282    public void validateInput(RequestDocument requestDocument, Object object, List<String> valuesList) throws OleDocStoreException {
283        Session session = (Session) object;
284        validateItem(requestDocument, session, valuesList);
285    }
286
287
288    public void validateNewItem(RequestDocument linkedRequestDocument, Session session, List<String> fieldValues, String instanceUuid) throws OleDocStoreException {
289        try {
290            String itemContent = linkedRequestDocument.getContent().getContent();
291            ItemOlemlRecordProcessor itemOlemlRecordProcessor = new ItemOlemlRecordProcessor();
292            Item item = itemOlemlRecordProcessor.fromXML(itemContent);
293            itemBarcodeValidation(item, fieldValues, null);
294            if (item.getCallNumber() != null) {
295                Node instanceNode = nodeManager.getNodeByUUID(session, instanceUuid);
296                if (instanceNode != null && instanceNode.hasNode(ProcessParameters.NODE_HOLDINGS)) {
297                    Node holdingsParentNode = instanceNode.getNode(ProcessParameters.NODE_HOLDINGS);
298                    if (holdingsParentNode.hasNode(ProcessParameters.FILE_HOLDINGS)) {
299                        Node holdingsNode = holdingsParentNode.getNode(ProcessParameters.FILE_HOLDINGS);
300                        if (holdingsNode != null) {
301                            getHoldingsContentNValidateItem(holdingsNode, item);
302                        }
303                    }
304                }
305            }
306        } catch (Exception e) {
307            throw new OleDocStoreException(e.getMessage(), e);
308        }
309    }
310
311
312    public void validateItem(RequestDocument linkedRequestDocument, Session session, List<String> fieldValues) throws OleDocStoreException {
313        try {
314            String itemContent = linkedRequestDocument.getContent().getContent();
315            ItemOlemlRecordProcessor itemOlemlRecordProcessor = new ItemOlemlRecordProcessor();
316            Item item = itemOlemlRecordProcessor.fromXML(itemContent);
317            //TODO:Ignored this validation as it affecting check in operation for an existing barcode
318            itemBarcodeValidation(item, fieldValues, linkedRequestDocument.getId());
319            if (item.getCallNumber() != null) {
320                Node node = nodeManager.getNodeByUUID(session, linkedRequestDocument.getUuid());
321                Node parentNode = null;
322                parentNode = node.getParent();
323                if (parentNode != null) {
324                    if (parentNode.hasNode(ProcessParameters.FILE_HOLDINGS)) {
325                        Node holdingsNode = parentNode.getNode(ProcessParameters.FILE_HOLDINGS);
326                        getHoldingsContentNValidateItem(holdingsNode, item);
327                    }
328                }
329            }
330        } catch (Exception e) {
331            throw new OleDocStoreException(e.getMessage(), e);
332        }
333    }
334
335    public void itemBarcodeValidation(Item item, List<String> fieldValues, String id) throws OleDocStoreException {
336        if (item.getAccessInformation() != null && StringUtils.isNotEmpty(item.getAccessInformation().getBarcode())) {
337            try {
338                if (fieldValues.contains(item.getAccessInformation().getBarcode()) ||
339                        QueryServiceImpl.getInstance().isFieldValueExists(DocType.ITEM.getCode(), "ItemBarcode_display", item.getAccessInformation().getBarcode(), id)) {
340                    throw new OleDocStoreException("Barcode " + item.getAccessInformation().getBarcode() + " already exists ");
341                }
342                fieldValues.add(item.getAccessInformation().getBarcode());
343            } catch (Exception e) {
344                throw new OleDocStoreException(e.getMessage(), e);
345            }
346        }
347
348    }
349
350    private void getHoldingsContentNValidateItem(Node holdingsNode, Item item) throws Exception {
351        String content = checkOutContent(holdingsNode, DocFormat.OLEML.getCode(), "ole-khuntley");
352        HoldingOlemlRecordProcessor holdingOlemlRecordProcessor = new HoldingOlemlRecordProcessor();
353        OleHoldings oleHoldings = holdingOlemlRecordProcessor.fromXML(content);
354        CallNumber callNumber = item.getCallNumber();
355        validateCallNumber(callNumber, oleHoldings);
356    }
357
358
359}