/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * MetadataPersistenceHelper.java * Creation date: (30-Apr-02 12:19:35 PM) * By: Edward Lam */ package org.openquark.cal.metadata; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.util.List; import java.util.Locale; import org.openquark.cal.compiler.CodeQualificationMap; import org.openquark.cal.compiler.ModuleName; import org.openquark.cal.services.CALFeatureName; import org.openquark.cal.services.Status; import org.openquark.util.xml.BadXMLDocumentException; import org.openquark.util.xml.NamespaceInfo; import org.openquark.util.xml.XMLPersistenceHelper; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * A non-instantiable helper class to facilitate conversions between metadata objects and their XML representations. * Note the class XMLPersistenceHelper provides more general helper facilities. The facilities * below are specific to metadata. * * @author Edward Lam */ final class MetadataPersistenceHelper { /* * Not intended to be instantiated. */ private MetadataPersistenceHelper() { } /** * Creates the example metadata section at the given XML element. * @param example the CALExample to save * @param parentElement the XML element to add the section to */ public static void addExampleElement(Element parentElement, CALExample example) { // Add an example element Document document = parentElement.getOwnerDocument(); Element element = document.createElement(MetadataPersistenceConstants.EXAMPLE_SECTION_TAG); parentElement.appendChild(element); XMLPersistenceHelper.addTextElement(element, MetadataPersistenceConstants.DESCRIPTION_TAG, example.getDescription()); XMLPersistenceHelper.addBooleanElement(element, MetadataPersistenceConstants.EXAMPLE_EVALUATE_TAG, example.evaluateExample()); addExpressionElement(element, example.getExpression()); } /** * Creates the expression metadata section at the given XML element. * @param expression the CALExpression to save * @param parentElement the XML element to add the section to */ public static void addExpressionElement(Element parentElement, CALExpression expression) { // Add an expression element Document document = parentElement.getOwnerDocument(); Element element = document.createElement(MetadataPersistenceConstants.EXPRESSION_SECTION_TAG); parentElement.appendChild(element); if (expression == null) { return; } XMLPersistenceHelper.addTextElement(element, MetadataPersistenceConstants.EXPRESSION_MODULE_CONTEXT_TAG, expression.getModuleContext().toSourceText()); XMLPersistenceHelper.addTextElement(element, MetadataPersistenceConstants.EXPRESSION_CAL_TEXT_TAG, expression.getExpressionText()); XMLPersistenceHelper.addTextElement(element, MetadataPersistenceConstants.EXPRESSION_QUALIFIED_CAL_TEXT_TAG, expression.getQualifiedExpressionText()); expression.getQualificationMap().saveToXML(element); } /** * Get the CALExample encoded in a given element. * @param element the root element of the example section * @return the CALExample represented by the example section * @throws BadXMLDocumentException */ public static CALExample getElementExampleValue(Node element) throws BadXMLDocumentException { XMLPersistenceHelper.checkIsTagElement(element, MetadataPersistenceConstants.EXAMPLE_SECTION_TAG); List<Element> elements = XMLPersistenceHelper.getChildElements(element); Element descriptionElement = elements.get(0); XMLPersistenceHelper.checkTag(descriptionElement, MetadataPersistenceConstants.DESCRIPTION_TAG); String description = XMLPersistenceHelper.getElementStringValue(descriptionElement); Element evaluateElement = elements.get(1); XMLPersistenceHelper.checkTag(evaluateElement, MetadataPersistenceConstants.EXAMPLE_EVALUATE_TAG); boolean evaluate = XMLPersistenceHelper.getElementBooleanValue(evaluateElement); Element expressionElement = elements.get(2); XMLPersistenceHelper.checkTag(expressionElement, MetadataPersistenceConstants.EXPRESSION_SECTION_TAG); CALExpression expression = getElementExpressionValue(expressionElement); return new CALExample(expression, description, evaluate); } /** * Gem the CALExpression encoded in a given element. * @param element the root element of the expression section * @return the CALExpression represented by the expression section * @throws BadXMLDocumentException */ public static CALExpression getElementExpressionValue(Node element) throws BadXMLDocumentException { XMLPersistenceHelper.checkIsTagElement(element, MetadataPersistenceConstants.EXPRESSION_SECTION_TAG); List<Element> elements = XMLPersistenceHelper.getChildElements(element); if (elements.isEmpty()) { return null; } Element moduleElement = elements.get(0); XMLPersistenceHelper.checkTag(moduleElement, MetadataPersistenceConstants.EXPRESSION_MODULE_CONTEXT_TAG); String moduleContextString = XMLPersistenceHelper.getElementStringValue(moduleElement); Element textElement = elements.get(1); XMLPersistenceHelper.checkTag(textElement, MetadataPersistenceConstants.EXPRESSION_CAL_TEXT_TAG); String calText = XMLPersistenceHelper.getElementStringValue(textElement); String qualifiedCalText = null; CodeQualificationMap qualificationMap = new CodeQualificationMap(); if (elements.size() > 2) { // This check is done for backwards compatibility; the following code // is executed only for expressions which contain a qualification map. Element textElement2 = elements.get(2); XMLPersistenceHelper.checkTag(textElement2, MetadataPersistenceConstants.EXPRESSION_QUALIFIED_CAL_TEXT_TAG); qualifiedCalText = XMLPersistenceHelper.getElementStringValue(textElement2); qualificationMap.loadFromXML((Element)element); } if (calText == null) { calText = ""; } if (qualifiedCalText == null) { qualifiedCalText = ""; } ModuleName moduleContext = ModuleName.make(moduleContextString); return new CALExpression(moduleContext, calText, qualificationMap, qualifiedCalText); } /** * Saves the given metadata object to the given file. * @param metadata the metadata object to save * @param metadataOutputStream the stream to save the metadata to */ static void saveMetadata(CALFeatureMetadata metadata, OutputStream metadataOutputStream) { // Convert the metadata into an XML document Document document = XMLPersistenceHelper.getEmptyDocument(); metadata.saveXML(document); // Attach namespace and schema information to the document element NamespaceInfo metadataNSInfo = CALFeatureMetadata.getNamespaceInfo(); XMLPersistenceHelper.attachNamespaceAndSchema(document, metadataNSInfo, MetadataPersistenceConstants.METADATA_SCHEMA_LOCATION, MetadataPersistenceConstants.METADATA_NS); // Write the document to the metadata file BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(metadataOutputStream); XMLPersistenceHelper.documentToXML(document, bufferedOutputStream, false); } /** * Load metadata from an input stream. * @param featureName the name of the feature associated with the metadata resource * @param locale the locale to be associated with the metadata object. * @param metadataInStream the stream to load the metadata from * @param importStatus the tracking status object * @return the metadata object the metadata was stored in (same as the passed in object). */ static CALFeatureMetadata loadMetadata(CALFeatureName featureName, Locale locale, InputStream metadataInStream, Status importStatus) { try { BufferedInputStream bufferedInStream = new BufferedInputStream(metadataInStream); // Create an empty metadata for loading. CALFeatureMetadata metadata = MetadataManager.getEmptyMetadata(featureName, locale); // Create a document from the stream and load the metadata from it. Document document = XMLPersistenceHelper.documentFromXML((bufferedInStream)); metadata.loadXML(document.getDocumentElement()); return metadata; } catch (XMLPersistenceHelper.DocumentConstructionException ex) { // This can happen for invalid metadata files. importStatus.add(new Status(Status.Severity.WARNING, "Metadata file is invalid for: " + featureName, ex)); } catch (BadXMLDocumentException ex) { // This can happen for invalid metadata files. importStatus.add(new Status(Status.Severity.WARNING, "Metadata file is invalid for: " + featureName, ex)); } catch (Exception ex) { // Not sure what happened here. importStatus.add(new Status(Status.Severity.WARNING, "Unknown exception while loading metadata for: " + featureName, ex)); } // An error occurred during loading so return the default empty metadata. return MetadataManager.getEmptyMetadata(featureName, locale); } }