/* * ClientFgdcHelper.java * * Created on June 25, 2007, 9:58 AM * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package edu.ucsb.nceas.metacat.clientview; import edu.ucsb.nceas.metacat.client.MetacatException; import edu.ucsb.nceas.utilities.XMLUtilities; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.StringReader; import java.util.HashMap; import java.util.Iterator; import java.util.Properties; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.DocumentType; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * * @author barteau */ public abstract class ClientFgdcHelper { private static XPath xpath = XPathFactory.newInstance().newXPath(); /** * Data Document ID location within an FGDC document. XPath expression. */ public static final String FGDC_DATA_FILE_DOCID_XPATH = "/metadata/distinfo/stdorder/digform/digtopt/onlinopt/computer/networka/networkr"; public static final String FGDC_DATA_FILE_QUERY_XPATH = FGDC_DATA_FILE_DOCID_XPATH + "[text()='%1s']"; public static final String FGDC_DATA_FILE_NAME_XPATH = "digtinfo/formcont"; /** * FGDC Data Document ID location within an FGDC document, relative to the "distinfo" parent node. * XPath expression. */ public static final String FGDC_DATA_FILE_NODES_XPATH = "stdorder/digform/digtopt/onlinopt/computer/networka/networkr"; public static final String PATH4ANCESTOR = FGDC_DATA_FILE_DOCID_XPATH + "[text()='%1s']/ancestor::node()[name()='%2s']"; public static final String SUB_DOCS_PATH = FGDC_DATA_FILE_DOCID_XPATH + "/text()"; /** * Metadata Document ID location within an FGDC document. XPath expression. */ public static final String FGDC_DOCID_XPATH = "/metadata/distinfo/resdesc"; public static final String FGDC_FILE_NAME_XPATH = "custom"; /** * Metadata Document ID query template within an FGDC document. Substitute %1s with Doc Id. */ public static final String XPATH_QUERY_TEMPLATE = FGDC_DOCID_XPATH + "[text()='%1s']"; public static final String FGDC_DOCID_ROOT_XPATH = XPATH_QUERY_TEMPLATE + "/ancestor::node()[name()='distinfo']"; /** * Identifies the FGDC DTD. */ public static final String FGDC_SYSTEM_ID = "http://www.fgdc.gov/metadata/fgdc-std-001-1998.dtd"; /** * Handles a client's request to delete a document. * If its a data document, it removes the Doc Id from the FGDC metadata in the * Metacat database. It determines what metadata Doc ID is including this Doc Id. * It then queries metacat for the parent FGDC document and removes the Doc Id from it, and * reloads the new version with a new revision number. * If its a metadata document, it deletes any related data documents, then it * deletes the metadata. In either instance, it sets the server feedback in * the session ("updateFeedback"). * @param request HttpServletRequest which contains docId parameter. */ public static void clientDeleteRequest(ClientView clientViewBean, ClientViewHelper clientViewHelper) { String result = null, docId, subDocId, parentDocId, revisedDocId; NodeList nodeLst; Node node; Document resultSetDoc; docId = clientViewBean.getDocId(); try { //*** First, determine what metadata file is including this file (if any). resultSetDoc = clientViewHelper.query(FGDC_DATA_FILE_DOCID_XPATH, docId, null); parentDocId = xpath.evaluate("/resultset/document/docid", resultSetDoc.getDocumentElement()); if (parentDocId != null && !parentDocId.equals("")) { clientViewHelper.setMetadataDoc(parentDocId); //*** Remove Doc Id from any parent metadata document. revisedDocId = removeDataDocIdFromFGDC(docId, parentDocId, clientViewHelper); clientViewBean.setDocId(revisedDocId); //*** Set the new Metadata Doc Id in the bean. clientViewBean.setMetaFileDocId(revisedDocId); } else { clientViewHelper.setMetadataDoc(docId); //*** This is a metadata document, so remove all of the sub-docId's. nodeLst = (NodeList) xpath.evaluate(SUB_DOCS_PATH, clientViewHelper.getMetadataDoc().getDocumentElement(), XPathConstants.NODESET); for(int i = 0; i < nodeLst.getLength(); i++) { node = nodeLst.item(i); subDocId = node.getNodeValue(); //*** Remove the sub-document. try { clientViewHelper.getMetacatClient().delete(subDocId); } catch (MetacatException ex) { ex.printStackTrace(); } } //*** We're deleting the Meta data doc, so clear it from the bean. clientViewBean.setMetaFileDocId(null); } //*** Remove the document. result = clientViewHelper.getMetacatClient().delete(docId); //*** Save the server feedback in the session, to be used by the view. clientViewBean.setMessage(ClientView.DELETE_MESSAGE, result); } catch (Exception ex) { ex.printStackTrace(); } } private static String removeDataDocIdFromFGDC(String docId, String parentDocId, ClientViewHelper clientViewHelper) throws Exception { String pathToDigform, revision = "", xPathQuery, tmp; Document doc; InputStream response; Properties prop; Node node; NodeList nodeLst; Reader reader; //*** Get the metadata document and remove the digform branch. doc = clientViewHelper.getMetadataDoc(); if (doc != null) { tmp = PATH4ANCESTOR.replaceFirst("%1s", docId); pathToDigform = tmp.replaceFirst("%2s", "digform"); node = (Node) xpath.evaluate(pathToDigform, doc.getDocumentElement(), XPathConstants.NODE); node.getParentNode().removeChild(node); xPathQuery = XPATH_QUERY_TEMPLATE.replaceFirst("%1s", parentDocId); revision = clientViewHelper.nextVersion(parentDocId, xPathQuery); reader = XMLUtilities.getDOMTreeAsReader(doc.getDocumentElement(), false); clientViewHelper.getMetacatClient().update(revision, reader, null); } return(revision); } public static boolean handlePackageUpload(String metaDocId, HashMap dataDocIDs, String contactName, String metaFNm, Document metadataDoc) throws IOException { boolean result = true; Node newBranch, metaRootNode; //*** Store the User Name and Doc Id in the FGDC document. newBranch = getFGDCdisinfo(contactName, metaDocId, metaFNm, dataDocIDs); //System.out.println("ClientFgdcHelper.handlePackageUpload: " + XMLUtilities.getDOMTreeAsString(newBranch)); metaRootNode = addDistInfoToFGDC(newBranch, metadataDoc); return(result); } public static boolean isFGDC(Document metadataDoc) { boolean result = false; DocumentType docType; String sysId; final String FGDC_TEST_EXPRESSION = "/metadata/idinfo/citation/citeinfo/title"; Node node = null; //*** First, try the rigid proper way of determining it. if (metadataDoc != null) { docType = metadataDoc.getDoctype(); if (docType != null) { sysId = docType.getSystemId(); if (sysId != null) result = (sysId.indexOf(FGDC_SYSTEM_ID) > -1); } } //*** It might not have a doc type line, so try another method. if (metadataDoc != null && !result) { try { node = (Node) xpath.evaluate(FGDC_TEST_EXPRESSION, metadataDoc.getDocumentElement(), XPathConstants.NODE); } catch (XPathExpressionException ex) { ex.printStackTrace(); } result = (node != null); } return(result); } public static boolean hasMetacatInfo(String docId, Document metadataDoc) { boolean result = false; String queryResult, xPathQuery; //xPathQuery = String.format(XPATH_QUERY_TEMPLATE, docId); xPathQuery = XPATH_QUERY_TEMPLATE.replaceFirst("%1s", docId); try { queryResult = xpath.evaluate(xPathQuery, metadataDoc); result = (queryResult != null && !queryResult.equals("")); } catch (XPathExpressionException ex) { ex.printStackTrace(); } return(result); } private static Node getFGDCdisinfo(String contactName, String resourceDescription, String metaFNm, HashMap dataDocIDs) throws IOException { Node result = null, node, digformBranch, formname, stdorder, formcont; Document doc; Iterator iterIt; String key, value, fileInfo[]; //*** This is a valid/minimal FGDC "distinfo" branch. final String XML = "" + " " + " " + " " + " " + " " + " " + " " + "
" + " " + " " + " " + " " + "
" + " " + "
" + "
" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "
"; doc = XMLUtilities.getXMLReaderAsDOMDocument(new StringReader(XML)); result = doc.getDocumentElement(); try { //*** Set the Contact Person. node = (Node) xpath.evaluate("/distinfo/distrib/cntinfo/cntperp/cntper", result, XPathConstants.NODE); ClientViewHelper.setTextContent(xpath, node, contactName); //node.setTextContent(contactName); Not in java 1.4 //*** Set the metadata Doc Id. node = (Node) xpath.evaluate("/distinfo/resdesc", result, XPathConstants.NODE); ClientViewHelper.setTextContent(xpath, node, resourceDescription); //node.setTextContent(resourceDescription); Not in java 1.4 //*** Set the metadata filename. node = (Node) xpath.evaluate("/distinfo/custom", result, XPathConstants.NODE); ClientViewHelper.setTextContent(xpath, node, metaFNm); //node.setTextContent(metaFNm); Not in java 1.4 //*** Loop thru the files, setting their format and Doc Id. stdorder = (Node) xpath.evaluate("/distinfo/stdorder", result, XPathConstants.NODE); digformBranch = (Node) xpath.evaluate("/distinfo/stdorder/digform", result, XPathConstants.NODE); iterIt = dataDocIDs.keySet().iterator(); while(iterIt.hasNext()) { //*** Save the data file Doc ID (required). key = (String) iterIt.next(); node = (Node) xpath.evaluate("digtopt/onlinopt/computer/networka/networkr", digformBranch, XPathConstants.NODE); ClientViewHelper.setTextContent(xpath, node, key); //node.setTextContent(key); fileInfo = (String[]) dataDocIDs.get(key); if (fileInfo != null) { //*** Save the data file format (optional). formname = (Node) xpath.evaluate("digtinfo/formname", digformBranch, XPathConstants.NODE); if ((value = fileInfo[ClientView.FORMAT_TYPE]) != null && !value.equals("")) { ClientViewHelper.setTextContent(xpath, formname, value); //formname.setTextContent(value); } else { //*** We did a deep clone of the branch, so clear prior contents. ClientViewHelper.setTextContent(xpath, formname, ""); //formname.setTextContent(""); } //*** Save the data file name. formcont = (Node) xpath.evaluate("digtinfo/formcont", digformBranch, XPathConstants.NODE); if ((value = fileInfo[ClientView.FILE_NAME]) != null && !value.equals("")) { ClientViewHelper.setTextContent(xpath, formcont, value); //formcont.setTextContent(value); } else { //*** We did a deep clone of the branch, so clear prior contents. ClientViewHelper.setTextContent(xpath, formcont, ""); //formcont.setTextContent(""); } } //*** Clone branch for next file. if (iterIt.hasNext()) { digformBranch = digformBranch.cloneNode(true); stdorder.appendChild(digformBranch); } } } catch (XPathExpressionException ex) { ex.printStackTrace(); } return(result); } private static Node addDistInfoToFGDC(Node newBranch, Document metadataDoc) { Node result = null, node; if (newBranch != null) { result = metadataDoc.getDocumentElement(); try { //*** Get a reference to the FGDC required "metainfo" node (only 1 allowed). node = (Node) xpath.evaluate("/metadata/metainfo", result, XPathConstants.NODE); if (node != null) { newBranch = metadataDoc.importNode(newBranch, true); //*** Add the new "distinfo" before it. result.insertBefore(newBranch, node); } } catch (XPathExpressionException ex) { ex.printStackTrace(); } } return(result); } public static void updateFileNameAndType(Node root, String dataDocId, String[] fileInfo) { Node digform; String tmp, pathToDigform; final String FORMNAME_PATH = "digtinfo/formname"; //*** File format type. final String FORMCONT_PATH = "digtinfo/formcont"; //*** Original file name. tmp = PATH4ANCESTOR.replaceFirst("%1s", dataDocId); pathToDigform = tmp.replaceFirst("%2s", "digform"); digform = ClientViewHelper.getNode(xpath, pathToDigform, root); if (digform != null) { ClientViewHelper.updateNodeText(digform, xpath, FORMNAME_PATH, fileInfo[ClientView.FORMAT_TYPE]); ClientViewHelper.updateNodeText(digform, xpath, FORMCONT_PATH, fileInfo[ClientView.FILE_NAME]); } } public static void updateMetadataFileName(Node root, String metadataDocId, String fileName) { String pathToResdesc; Node resdesc; if (fileName != null && !fileName.equals("")) { pathToResdesc = XPATH_QUERY_TEMPLATE.replaceFirst("%1s", metadataDocId); ClientViewHelper.updateNodeText(root, xpath, pathToResdesc, metadataDocId); } } }