/* See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * Esri Inc. licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.esri.gpt.catalog.arcims; import com.esri.gpt.framework.security.codec.Base64; import com.esri.gpt.framework.util.Val; import com.esri.gpt.framework.xml.DomUtil; import com.esri.gpt.framework.xml.XmlIoUtil; import com.esri.gpt.framework.xml.XsltTemplate; import com.esri.gpt.framework.xml.XsltTemplates; import java.io.IOException; import java.util.HashMap; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.SAXException; /** * Handles the translation of documents to EsriIso format. * <p/> * When a schema is neither FGDC or ISO19115, the document must * be translated to ISO19115 and enclosed as a binary node prior * to publishing to the ArcIMS metdata server. * <p/> * The translation process uses a Java implementation of a metadata * document transformation mechanism developed for ArcGIS Desktop. * <p/> * The underlying files for the process are stored within: * gpt/metadata/ArcGIS_Translator * <p/> * The API for translation is found within esri-translator.jar. */ public class EsriIsoTranslator { // class variables ============================================================= private static XsltTemplates XSLTTEMPLATES = new XsltTemplates(); // instance variables ========================================================== // constructors ================================================================ /** Default constructor. */ public EsriIsoTranslator() {} // properties ================================================================== // methods ===================================================================== /** * Gets a compiled XSLT template. * @param xsltPath the path to an XSLT * @return the compiled template * @throws IOException if an IO exception occurs * @throws TransformerException if a transformation exception occurs * @throws SAXException if a SAX parsing exception occurs */ private synchronized XsltTemplate getCompiledTemplate(String xsltPath) throws TransformerException { String sKey = xsltPath; XsltTemplate template = XSLTTEMPLATES.get(sKey); if (template == null) { template = XsltTemplate.makeTemplate(xsltPath); XSLTTEMPLATES.put(sKey,template); } return template; } /** * Inserts a document enclosure into an EsriIso document. * @param dom the EsriIso document * @param originalXml the original XML for the document to enclose * @throws IOException if an IO exception occurs */ private void insertEnclosure(Document dom, String originalXml) throws IOException { /* Structure for an enclosed document: <metadata> <Binary> <Enclosure> <Data SourceMetadata="yes" OriginalFileName="source_metadata.xml" SourceMetadataDigest="0e6a7512e472b810acb569c1714fdc" EsriPropertyType="Base64">base64</Data> </Enclosure> </Binary> </metadata> Other possible Data attributes: enclosure="process" SourceMetadataDocId="{//gmd:fileIdentifier[1]/gco:CharacterString}" */ // ensure the Binary node Node ndRoot = dom.getDocumentElement(); Node ndBinary = DomUtil.findFirst(ndRoot,"Binary"); if (ndBinary == null) { ndBinary = dom.createElement("Binary"); ndBinary = ndRoot.appendChild(ndBinary); } // ensure the Enclosure node Node ndEnclosure = DomUtil.findFirst(ndBinary,"Enclosure"); if (ndEnclosure == null) { ndEnclosure = dom.createElement("Enclosure"); ndEnclosure = ndBinary.appendChild(ndEnclosure); } // remove an existing Data node, recreate the Data node Node ndData = DomUtil.findFirst(ndEnclosure,"Data"); if (ndData != null) { ndEnclosure.removeChild(ndData); } ndData = dom.createElement("Data"); ndData = ndEnclosure.appendChild(ndData); // set attributes Attr attr; // property type attr = dom.createAttribute("EsriPropertyType"); attr.setValue("Base64"); ndData.getAttributes().setNamedItem(attr); // MD5 hash of the original xml for the document, // this is not yet implemented /* String sMd5Hash = ""; try { MessageDigest md; md = MessageDigest.getInstance("MD5"); md.update(originalXml.getBytes("UTF-8")); //String sTmp = new String(md.digest(),"UTF-8"); //System.err.println(sTmp); } catch (NoSuchAlgorithmException e) { // should never happen e.printStackTrace(System.err); } catch (UnsupportedEncodingException e) { // should never happen e.printStackTrace(System.err); } if ((sMd5Hash != null) && (sMd5Hash.length() > 0)) { attr = dom.createAttribute("SourceMetadataDigest"); attr.setValue(sMd5Hash); ndData.getAttributes().setNamedItem(attr); } */ // file name attr = dom.createAttribute("OriginalFileName"); attr.setValue("source_metadata.xml"); ndData.getAttributes().setNamedItem(attr); // source metadata flag attr = dom.createAttribute("SourceMetadata"); attr.setValue("yes"); ndData.getAttributes().setNamedItem(attr); // add the text node String sBase64 = Base64.encode(originalXml,null); Node ndText = dom.createTextNode(sBase64); ndText = ndData.appendChild(ndText); } /** * Transforma an original XML string to EsriIso format, then * encloses the original XML as a base64 node with the EsriIso document. * @param uuid the document UUID * @param fileIdentifier the file identifier * @param originalXml the original XML string for the metadata document * @param toEsriIsoXslt the path to an XSLT that generates the EsriIso document * @return the EsriIso document * @throws TransformerException if a transformation exception occurs * @throws ParserConfigurationException if a configuration exception occurs * @throws SAXException if an exception occurs during XML parsing * @throws IOException if an i/o exception occurs */ public String transformAndEnclose(String uuid, String fileIdentifier, String originalXml, String toEsriIsoXslt) throws TransformerException, ParserConfigurationException, SAXException, IOException { HashMap<String,String> params = new HashMap<String,String>(); params.put("documentUuid",Val.chkStr(uuid)); params.put("fileIdentifier",Val.chkStr(fileIdentifier)); XsltTemplate template = getCompiledTemplate(toEsriIsoXslt); String sXml = template.transform(originalXml,params); Document dom = DomUtil.makeDomFromString(sXml,false); insertEnclosure(dom,originalXml); return XmlIoUtil.domToString(dom); } }