All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dtolabs.shared.resources.ResourceXMLParser Maven / Gradle / Ivy

There is a newer version: 5.6.0-20240912
Show newest version
/*
 * Copyright 2016 SimplifyOps, Inc. (http://simplifyops.com)
 *
 * Licensed 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.
 */

/*
* ResourceXMLParser.java
* 
* User: Greg Schueler [email protected]
* Created: Apr 23, 2010 3:35:55 PM
* $Id$
*/
package com.dtolabs.shared.resources;

import static com.dtolabs.shared.resources.ResourceXMLConstants.*;

import org.dom4j.*;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;

import java.io.*;
import java.util.*;

/**
 * ResourceXMLParser parses a resources.xml formatted file, and provides several interfaces for using the result data.
 * 
* The {@link #parse()} method parses the configured File as a sequence of {@link com.dtolabs.shared.resources.ResourceXMLParser.Entity} * objects, one for each entry in the file. It passes these objects to any configured {@link com.dtolabs.shared.resources.ResourceXMLReceiver} * object. One should be set using {@link * #setReceiver(ResourceXMLReceiver)} to receive parsed entities or the entire entity set. *
* The default entityXpath property value is set to match all entity types in the resource xml * (node|setting|package|deployment), but this can be set to any Xpath to limit the entities that are * parsed from the document. (e.g. "node|package" or "node[@name='mynode']"). *
* * @author Greg Schueler [email protected] * @version $Revision$ */ public class ResourceXMLParser { static Logger log4j = LoggerFactory.getLogger(ResourceXMLParser.class.getName()); private File file; private InputStream input; private Document doc; private ResourceXMLReceiver receiver; public static final String DEFAULT_ENTITY_XPATH = NODE_ENTITY_TAG ; private String entityXpath = DEFAULT_ENTITY_XPATH; /** * Constructor for the ResourceXMLParser * * @param file source file */ public ResourceXMLParser(final File file) { this.file = file; } /** * Constructor for the ResourceXMLParser * * @param input source file */ public ResourceXMLParser(final InputStream input) { this.input = input; } /** * Constructor for the ResourceXMLParser * * @param doc source document */ public ResourceXMLParser(final Document doc) { this.doc = doc; } /** * Parse the document, applying the configured Receiver to the parsed entities * * @throws ResourceXMLParserException parse error * @throws java.io.IOException io error */ public void parse() throws ResourceXMLParserException, IOException { final EntityResolver resolver = createEntityResolver(); final SAXReader reader = new SAXReader(false); reader.setEntityResolver(resolver); try { final Document doc; if(null==this.doc){ final InputStream in; if(null!=file){ in = new FileInputStream(file); }else{ in = input; } try{ doc=reader.read(in); }finally{ if(null!=file){ in.close(); } } }else{ doc=this.doc; } final EntitySet set = new EntitySet(); final Element root = doc.getRootElement(); final List list = root.selectNodes(entityXpath); for (final Object n : list) { final Node node = (Node) n; final Entity ent = parseEnt(node, set); if (null != receiver) { if (!receiver.resourceParsed(ent)) { break; } } } if (null != receiver) { receiver.resourcesParsed(set); } } catch (DocumentException e) { throw new ResourceXMLParserException(e); } } public static EntityResolver createEntityResolver() { return new EntityResolver() { public InputSource resolveEntity(final String publicId, final String systemId) { if (publicId.equals(DTD_PROJECT_DOCUMENT_1_0_EN)) { final InputStream in = ResourceXMLParser.class.getClassLoader().getResourceAsStream( PROJECT_DTD_RESOURCE_PATH); if (null != in) { return new InputSource(in); } else { System.err.println( "couldn't load resource " + PROJECT_DTD_RESOURCE_PATH + ":" + ResourceXMLParser.class .getClassLoader().getResource(PROJECT_DTD_RESOURCE_PATH)); final File file1 = new File("src/java/" + PROJECT_DTD_RESOURCE_PATH); if (file1.exists()) { try { return new InputSource(new FileInputStream(file1)); } catch (FileNotFoundException e) { e.printStackTrace(); } } } } return null; } }; } /** * Given xml Node and EntitySet, parse the entity defined in the Node * * @param node DOM node * @param set entity set holder * * @return parsed Entity object * * @throws ResourceXMLParserException if entity definition was previously found, or another error occurs */ private Entity parseEnt(final Node node, final EntitySet set) throws ResourceXMLParserException { final Entity ent = parseResourceRef(set, node); ent.setResourceType(node.getName()); parseEntProperties(ent, node); parseEntSubAttributes(ent, node); return ent; } /** * Parse a simple resource/entity node for the type/name attributes, returning a new or existing Entity * * @param set entity set * @param n entity DOM node * * @return new or existing Entity * * @throws ResourceXMLParserException if the ndoe is missing the required attributes */ private Entity parseResourceRef(final EntitySet set, final Node n) throws ResourceXMLParserException { final Node node2 = n.selectSingleNode("@" + COMMON_NAME); if (null == node2) { throw new ResourceXMLParserException("@" + COMMON_NAME + " required: " + reportNodeErrorLocation(n)); } final String rname = node2.getStringValue(); return set.getOrCreateEntity( rname); } private static final HashMap entityProperties = new HashMap(); static { entityProperties.put(NODE_ENTITY_TAG, nodeProps); } /** * Parse the DOM attributes as properties for the particular entity node type * * @param ent Entity object * @param node entity DOM node * * @throws ResourceXMLParserException if the DOM node is an unexpected tag name */ private void parseEntProperties(final Entity ent, final Node node) throws ResourceXMLParserException { if (null == entityProperties.get(node.getName())) { throw new ResourceXMLParserException( "Unexpected entity declaration: " + node.getName() + ": " + reportNodeErrorLocation(node)); } final Element node1 = (Element) node; //load all element attributes as properties for (final Object o : node1.attributes()) { final Attribute attr = (Attribute) o; ent.properties.setProperty(attr.getName(), attr.getStringValue()); } } /** * Parse the DOM attributes as properties for the particular entity node type * * @param ent Entity object * @param node entity DOM node * * @throws ResourceXMLParserException if the DOM node is an unexpected tag name */ private void parseEntSubAttributes(final Entity ent, final Node node) throws ResourceXMLParserException { final Element node1 = (Element) node; //load all sub elements called "attribute" as properties for (final Object attribute : node1.selectNodes(ATTRIBUTE_TAG)) { Element attr=(Element) attribute; if(null==attr.selectSingleNode("@" + ATTRIBUTE_NAME_ATTR)) { throw new ResourceXMLParserException( ATTRIBUTE_TAG + " element has no '" + ATTRIBUTE_NAME_ATTR + "' attribute: " + reportNodeErrorLocation(attr)); } String attrname = attr.selectSingleNode("@" + ATTRIBUTE_NAME_ATTR).getStringValue(); String attrvalue; //look for "value" attribute if(null!=attr.selectSingleNode("@"+ATTRIBUTE_VALUE_ATTR)) { attrvalue = attr.selectSingleNode("@" + ATTRIBUTE_VALUE_ATTR).getStringValue(); }else if(null!= attr.getText()) { //look for text content attrvalue = attr.getText(); }else { throw new ResourceXMLParserException( ATTRIBUTE_TAG + " element has no '" + ATTRIBUTE_VALUE_ATTR + "' attribute or text content: " + reportNodeErrorLocation(attr)); } ent.properties.setProperty(attrname, attrvalue); } } /** * Return a String describing the DOM node's location and parent type name * * @param e the node * * @return string describing xpath location and parent "type" element name */ protected static String reportNodeErrorLocation(final Node e) { return "at xpath " + e.getUniquePath(); } /** * Return the ResourceXMLReceiver * * @return the ResourceXMLReceiver */ public ResourceXMLReceiver getReceiver() { return receiver; } /** * Set the ResourceXMLReceiver to use. It will be invoked to receive the {@link * com.dtolabs.shared.resources.ResourceXMLParser.Entity} objects created during the {@link #parse()} method, * and will also receive the complete {@link com.dtolabs.shared.resources.ResourceXMLParser.EntitySet} at the * end of the sequence. It can govern whether parsing should continue or not, see {@link * com.dtolabs.shared.resources.ResourceXMLReceiver} * * @param receiver the new ResourceXMLReceiver */ public void setReceiver(final ResourceXMLReceiver receiver) { this.receiver = receiver; } /** * Contains the set of parsed entities from the document. */ public static class EntitySet { private HashMap entcache = new HashMap(); void addEntity(final Entity ent) { entcache.put(ent.getId(), ent); } boolean containsEntity(final String name) { return entcache.containsKey(name); } Entity createEntity( final String name) { final Entity ent = new Entity(); ent.setName(name); ent.set = this; addEntity(ent); return ent; } Entity getOrCreateEntity(final String name) { if (containsEntity(name)) { return entcache.get(name); } return createEntity(name); } /** * Return the collection of entities. * * @return the entities. */ public Collection getEntities() { return entcache.values(); } } /** * Represents a parsed resource entity in the xml, which consists of a name property, a type property, and a set of * name/value properties. These property names correspond to the attribute names of the type of entity being * parsed. See {@link com.dtolabs.shared.resources.ResourceXMLConstants} for property names. *
* The specific entity declaration type (node,setting,package,deployment) can be found with the {@link * #getResourceType()} method. This method will return null if the entity is a resource-reference with no * corresponding entity definition in the XML. *
* Two special properties, "resources.replace" and "referrers.replace" correspond to the values of the "replace" * attribute on any embedded resource/referrer references for the entity. */ public static class Entity { private EntitySet set; Entity() { this.properties = new Properties(); } private Properties properties; private String name; private String resourceType; public String getId() { return name; } public String getName() { return name; } void setName(final String name) { this.name = name; } @Override public boolean equals(final Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } final Entity entity = (Entity) o; if (name != null ? !name.equals(entity.name) : entity.name != null) { return false; } return true; } @Override public int hashCode() { int result = set != null ? set.hashCode() : 0; result = 31 * result + (properties != null ? properties.hashCode() : 0); result = 31 * result + (name != null ? name.hashCode() : 0); return result; } public Properties getProperties() { return properties; } public String getProperty(final String prop) { return properties.getProperty(prop); } public void setProperty(final String prop, final String value) { properties.setProperty(prop, value); } /** * Return the name of the resource xml "tag" defining this entity, or null if it is a resource reference * * @return the name of the resource xml "tag" defining this entity, or null if it is a resource reference */ public String getResourceType() { return resourceType; } void setResourceType(final String resourceType) { this.resourceType = resourceType; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy