/******************************************************************************* * xFramium * * Copyright 2016 by Moreland Labs, Ltd. (http://www.morelandlabs.com) * * Some open source application is free software: you can redistribute * it and/or modify it under the terms of the GNU General Public * License as published by the Free Software Foundation, either * version 3 of the License, or (at your option) any later version. * * Some open source application is distributed in the hope that it will * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with xFramium. If not, see <http://www.gnu.org/licenses/>. * * @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+> *******************************************************************************/ package org.xframium.page.data.provider; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xframium.page.data.DefaultPageData; import org.xframium.page.data.PageData; // TODO: Auto-generated Javadoc /** * The Class XMLPageDataProvider. */ public class XMLPageDataProvider extends AbstractPageDataProvider { /** The Constant NAME. */ private static final String NAME = "name"; /** The Constant ACTIVE. */ private static final String ACTIVE = "active"; /** The Constant LOCK. */ private static final String LOCK = "lockRecords"; /** The x path factory. */ private XPathFactory xPathFactory; /** The file name. */ private File fileName; /** The resource name. */ private String resourceName; private byte[] resourceData; private boolean asResource = false; /** * Instantiates a new XML page data provider. * * @param fileName the file name */ public XMLPageDataProvider( File fileName ) { xPathFactory = XPathFactory.newInstance(); this.fileName = fileName; } /** * Instantiates a new XML page data provider. * * @param resourceName the resource name */ public XMLPageDataProvider( String resourceName ) { xPathFactory = XPathFactory.newInstance(); this.resourceName = resourceName; } public XMLPageDataProvider( byte[] resourceData ) { xPathFactory = XPathFactory.newInstance(); this.resourceData = resourceData; } /* (non-Javadoc) * @see com.perfectoMobile.page.data.provider.AbstractPageDataProvider#readPageData() */ @Override public void readPageData() { if ( resourceData != null ) { readElements( new ByteArrayInputStream( resourceData ) ); populateTrees(); } else if (fileName == null) { if (log.isInfoEnabled()) log.info( "Reading from CLASSPATH as " + resourceName ); asResource = true; readElements( getClass().getClassLoader().getResourceAsStream( resourceName ) ); populateTrees(); } else { try { if (log.isInfoEnabled()) log.info( "Reading from FILE SYSTEM as [" + fileName + "]" ); asResource = false; readElements( new FileInputStream( fileName ) ); populateTrees(); } catch (FileNotFoundException e) { log.fatal( "Could not read from " + fileName, e ); } } } /** * Read elements. * * @param inputStream the input stream */ private void readElements( InputStream inputStream ) { try { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); dbFactory.setNamespaceAware( true ); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document xmlDocument = dBuilder.parse( inputStream ); NodeList nodeList = getNodes( xmlDocument, "//data/recordType" ); for (int i = 0; i < nodeList.getLength(); i++) parseType( nodeList.item( i ) ); NodeList importList = getNodes( xmlDocument, "//data/import" ); if ( importList != null ) { for (int i = 0; i < importList.getLength(); i++) { Node importElement = importList.item( i ); String fileName = importElement.getAttributes().getNamedItem( "fileName" ).getNodeValue(); if (log.isInfoEnabled()) log.info( "Reading imported data as [" + fileName + "]" ); if ( asResource ) readElements( getClass().getClassLoader().getResourceAsStream( fileName ) ); else readElements( new FileInputStream( fileName ) ); } } } catch (Exception e) { log.fatal( "Error reading CSV Element File", e ); } } /** * Parses the type. * * @param siteNode the site node */ private void parseType( Node siteNode ) { String typeName = siteNode.getAttributes().getNamedItem( NAME ).getNodeValue(); Node lockNode = siteNode.getAttributes().getNamedItem( LOCK ); boolean lockRecords = false; if (lockNode != null) lockRecords = Boolean.parseBoolean( lockNode.getNodeValue() ); if (log.isDebugEnabled()) log.debug( "Extracted Record Type [" + typeName + "]" ); addRecordType( typeName, lockRecords ); NodeList nodeList = getNodes( siteNode.getOwnerDocument(), "//data/recordType[@name='" + typeName + "']/record" ); for (int i = 0; i < nodeList.getLength(); i++) parseRecord( typeName, nodeList.item( i ) ); } /** * Parses the record. * * @param typeName the type name * @param pageNode the page node */ private void parseRecord( String typeName, Node pageNode ) { if ( pageNode == null || pageNode.getAttributes() == null || pageNode.getAttributes().getNamedItem( NAME ) == null ) return; String recordName = pageNode.getAttributes().getNamedItem( NAME ).getNodeValue(); boolean active = true; Node activeNode = pageNode.getAttributes().getNamedItem( ACTIVE ); if ( activeNode != null ) active = Boolean.parseBoolean( activeNode.getNodeValue() ); if (log.isDebugEnabled()) log.debug( "Extracted Record [" + recordName + "]" ); DefaultPageData currentRecord = new DefaultPageData( typeName, recordName, active ); for (int i = 0; i < pageNode.getAttributes().getLength(); i++) { Node attributeNode = pageNode.getAttributes().item( i ); if (!attributeNode.getNodeName().equals( NAME )) { String currentName = attributeNode.getNodeName(); String currentValue = attributeNode.getNodeValue(); if ( currentValue.startsWith( PageData.TREE_MARKER ) && currentValue.endsWith( PageData.TREE_MARKER ) ) { // // This is a reference to another page data table // currentRecord.addPageData( currentName ); currentRecord.addValue( currentName + PageData.DEF, currentValue ); currentRecord.setContainsChildren( true ); } else currentRecord.addValue( currentName, currentValue ); } } for (int i = 0; i < pageNode.getChildNodes().getLength(); i++) { Node elementNode = pageNode.getChildNodes().item( i ); if (elementNode.getNodeType() == Node.ELEMENT_NODE) { String currentName = elementNode.getNodeName(); String currentValue = elementNode.getTextContent(); if ( currentValue.startsWith( PageData.TREE_MARKER ) && currentValue.endsWith( PageData.TREE_MARKER ) ) { // // This is a reference to another page data table // currentRecord.addPageData( currentName ); currentRecord.addValue( currentName + PageData.DEF, currentValue ); currentRecord.setContainsChildren( true ); } else currentRecord.addValue( currentName, currentValue ); } } addRecord( currentRecord ); } /** * Gets the nodes. * * @param xmlDocument the xml document * @param xPathExpression the x path expression * @return the nodes */ private NodeList getNodes( Document xmlDocument, String xPathExpression ) { try { if (log.isDebugEnabled()) log.debug( "Attempting to return Nodes for [" + xPathExpression + "]" ); XPath xPath = xPathFactory.newXPath(); return ( NodeList ) xPath.evaluate( xPathExpression, xmlDocument, XPathConstants.NODESET ); } catch (Exception e) { log.error( "Error parsing xPath Expression [" + xPathExpression + "]" ); return null; } } public static void main( String[] args ) { //XMLPageDataProvider x = new XMLPageDataProvider( new File( "C:\\Users\\Allen\\git\\xframium-java\\testing\\pageData\\pageData.xml" ) ); ExcelPageDataProvider x = new ExcelPageDataProvider( new File( "C:\\Users\\Allen\\git\\fordPass\\fordPass\\data\\pageData-STAGING.xlsx" ), "fordPassNA" ); x.readPageData(); //x.populateTrees(); System.out.println( x.toString() ); System.out.println( x.getRecords( "parentData.one.childRecord.childOne.loopData" ) ); } }