org.adl.validator.RulesValidator.java Source code

Java tutorial

Introduction

Here is the source code for org.adl.validator.RulesValidator.java

Source

/******************************************************************************
**
** Advanced Distributed Learning Co-Laboratory (ADL Co-Lab) Hub grants you 
** ("Licensee") a non-exclusive, royalty free, license to use, modify and 
** redistribute this software in source and binary code form, provided that 
** i) this copyright notice and license appear on all copies of the software; 
** and ii) Licensee does not utilize the software in a manner which is 
** disparaging to ADL Co-Lab Hub.
**
** This software is provided "AS IS," without a warranty of any kind.  ALL 
** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING 
** ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 
** OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.  ADL Co-Lab Hub AND ITS LICENSORS 
** SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
** USING, MODIFYING OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES.  IN NO 
** EVENT WILL ADL Co-Lab Hub OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, 
** PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, 
** INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE 
** THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE 
** SOFTWARE, EVEN IF ADL Co-Lab Hub HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
** DAMAGES.
**
******************************************************************************/
package org.adl.validator;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * <strong>Filename: </strong>RulesValidator.java<br><br>
 *
 * <strong>Description: </strong>The <code>RulesValidator</code>
 * object contains the information required for the SCORM Validation
 * Process performed by the SCORM Validator.  This object
 * will contain the DOM of the XML rules that are neccessary for
 * meeting conformance to each of the Application Profiles.<br><br>
 *
 * <strong>Design Issues: </strong><br><br>
 *
 * <strong>Implementation Issues: </strong><br><br>
 *
 * <strong>Known Problems: </strong><br><br>
 *
 * <strong>Side Effects: </strong><br><br>
 *
 * <strong>References: </strong><br><br>
 *
 * @author ADL Technical Team
 */
public class RulesValidator implements Serializable {
    /**
      * 
      */
    private static final long serialVersionUID = 1L;

    /**
       * The DOM of the application profile rules defined in xml.<br>
       */
    private Document mRulesDocument;

    /**
     * The validator type:
     *  <ul>
     *     <li><code>contentpackage</code></li>
     *     <li><code>metadata</code></li>
     *     <li><code>sequence</code></li>
     *  </ul>
     */
    private String mValidatorType;

    /**
     * Logger object used for debug logging.<br>
     */
    private static Log log = LogFactory.getLog(RulesValidator.class);

    /**
     * Default constructor - inializes the attributes for this class.<br>
     *
     * @param iValidatorType The validator that is currently being worked.
     * <ul>
     *    <li><code>contentpackage</code></li>
     *    <li><code>metadata</code></li>
     *    <li><code>sequence</code></li>
     * </ul>
     */
    public RulesValidator(String iValidatorType) {
        //mLogger = Logger.getLogger("org.adl.util.debug.validator");

        log.debug("RulesValidator()");

        mRulesDocument = null;
        mValidatorType = iValidatorType;

        log.debug("RulesValidator()");
    }

    /**
     * Retrieves the application profile that the xml rules describe.<br>
     *
     * @return String: The name of the application profile being tested<br>
     *
     */
    public String getApplicationProfile() {
        return getAttribute(mRulesDocument.getDocumentElement(), "appprof");
    }

    /**
     * Retrieves the value of the desired attribute.
     *
     * @param iNode Node which contains the attributes.
     *
     * @param iAttribute Name of the attribute desired
     *
     * @return String: Value of the desired attribute
     */
    protected String getAttribute(Node iNode, String iAttribute) {
        String returnValue = "";

        // grab attributes of the node
        Attr attrs[] = sortAttributes(iNode.getAttributes());

        // now see if the asked for attribute exists and send
        // back the value
        Attr attribute;
        for (Attr attr : attrs) {
            attribute = attr;

            //if ( attribute.getName().equals( theAttribute ) )
            if (attribute.getLocalName().equals(iAttribute)) {
                returnValue = attribute.getValue();
                break;
            }
        }
        return returnValue;
    }

    /**
     * Retrieves the vocabulary element for the specified element at the
     * at the specified path location.<br>
     *
     * @param iElementName Name of the element being searched for <br>
     *
     * @param iPath  Path of the element being searched for
     * (necessary for elements with same names but different values)<br>
     *
     * @param iAttribName Name of the attribute being tested<br>
     *
     * @return List:  List containing the vocabulary string values for the
     * specified rule at the specified element with the specified path.<br>
     */
    public List<String> getAttribVocabRuleValues(String iElementName, String iPath, String iAttribName) {
        log.debug("getAttribVocabRuleValues()");
        log.debug("    iElementName coming in is " + iElementName);
        log.debug("    iPath coming in is " + iPath);
        log.debug("    iAttribName coming in is " + iAttribName);

        List<Node> ruleNodeList;
        List<String> vocabList = new ArrayList<String>();

        if (mRulesDocument != null) {
            log.debug("mRulesDocument != null");

            ruleNodeList = retrieveAttribVocabRuleElements(iElementName, iPath, "vocab", iAttribName);
            int numVocabularies = ruleNodeList.size();

            if (numVocabularies != 0) {
                // loop through vocabulary nodes to retrieve value and add them
                // to the string List
                for (int i = 0; i < numVocabularies; i++) {
                    vocabList.add(getTaggedData((ruleNodeList.get(i))));
                }
            } else {
                log.debug("ruleNode is null - rules not found");
            }
        } else {
            log.error("Can not continue validation of rules, doc is null");
        }
        log.debug("getAttribVocabRuleValues()");

        return vocabList;
    }

    /**
     * Retrieves the element node's value for the specified string name
     * at the specified path location.<br>
     *
     * @param iElementName Name of the element being searched for<br>
     *
     * @param iPath  Path of the element being searched for
     * (necessary for elements with same names but different values)<br>
     *
     * @param iRuleName Name of the rule being retrieved<br>
     *                  <ul>
     *                     <li><code>min</code></li>
     *                     <li><code>max</code></li>
     *                     <li><code>spm</code></li>
     *                     <li><code>attrib</code></li>
     *                  </ul>
     *
     * @return Specified rule value of the specified element with the
     * specified path.<br>
     */
    public String getRuleValue(String iElementName, String iPath, String iRuleName) {
        log.debug("getRuleValue()");

        log.debug("    iElementName coming in is " + iElementName);
        log.debug("    iPath coming in is " + iPath);
        log.debug("    iRuleName coming in is " + iRuleName);

        String stringResult = "-1";
        Node ruleNode;

        if (mRulesDocument != null) {
            log.debug("mRulesDocument != null");

            ruleNode = retrieveRuleElement(iElementName, iPath, iRuleName);
            if (ruleNode != null) {
                // retrieve value and return
                log.debug("rule found, retrieving value");

                stringResult = getTaggedData(ruleNode);
            } else {
                log.debug("ruleNode is null - rull was not found");
            }
        } else {
            log.error("Can not continue validation of rules, doc is null");
        }
        log.debug("Returning the following value " + stringResult);
        log.debug("getRuleValue()");

        return stringResult;
    }

    /**
     * Retrieves the element node's value for the specified string name
     * at the specified path location.<br>
     *
     * @param iElementName Name of the element being searched for<br>
     *
     * @param iPath  Path of the element being searched for
     * (necessary for elements with same names but different values)<br>
     *
     * @param iRuleName Name of the rule being retrieved
     *                  <ul>
     *                     <li><code>min</code></li>
     *                     <li><code>max</code></li>
     *                     <li><code>spm</code></li>
     *                     <li><code>attrib</code></li>
     *                  </ul>
     *
     * @param iAttribAttribName Name of the attribute rule being retrieved.
     * <br><br>
     *
     * @return String: Value of specified rule for the specified element with the
     * specified path.<br>
     */
    public String getRuleValue(String iElementName, String iPath, String iRuleName, String iAttribAttribName) {
        log.debug("getRuleValue()");
        log.debug("    iElementName coming in is " + iElementName);
        log.debug("    iPath coming in is " + iPath);
        log.debug("    iRuleName coming in is " + iRuleName);
        log.debug("    iAttribAttribName coming in is " + iAttribAttribName);

        String stringResult = "-1";
        Node ruleNode;

        if (mRulesDocument != null) {
            log.debug("mRulesDocument != null");

            ruleNode = retrieveAttribRuleElement(iElementName, iPath, iRuleName, iAttribAttribName);

            if (ruleNode != null) {
                // retrieve value and return
                log.debug("rule found, retrieving value");

                stringResult = getTaggedData(ruleNode);
            } else {
                log.debug("ruleNode is null - rull was not found");
            }
        } else {
            log.error("Can not continue validation of rules, doc is null");
        }
        log.debug("Returning the following value " + stringResult);
        log.debug("getRuleValue()");

        return stringResult;
    }

    /**
     * Retrieves the text from a text node
     *
     * @param iNode   TEXT_NODE that contains the needed text
     *
     * @return String describing the text contained in the given node
     */
    public String getTaggedData(Node iNode) {
        log.debug("getTaggedData()");

        String value = "";
        NodeList kids = iNode.getChildNodes();

        //cycle through all children of node to get the text
        if (kids != null) {
            for (int i = 0; i < kids.getLength(); i++) {
                //make sure this is a "text node"
                if ((kids.item(i).getNodeType() == Node.TEXT_NODE)
                        || (kids.item(i).getNodeType() == Node.CDATA_SECTION_NODE)) {
                    value = value + kids.item(i).getNodeValue().trim();
                }
            }
        } else {
            log.debug("%%% no kids for value %%%");

        }
        log.debug("getTaggedData()");

        return value;
    }

    /**
     * Retrieves the type of XML subject the xml rules describe.<br>
     *
     * @return String containing the type of the test subject<br>
     *    ( "metadata" || "imsmanifest" || "sequence" )<br>
     */
    public String getType() {
        return getAttribute(mRulesDocument.getDocumentElement(), "type");
    }

    /**
     *
     * Retrieves the vocabulary element for the specified element at the
     * at the specified path location.<br>
     *
     * @param iElementName Name of the element being searched for <br>
     *
     * @param iPath  Path of the element being searched for
     * (necessary for elements with same names but different values)<br>
     *
     * @return A List of vocabulary string values for the specified rule at
     * the specified element with the specified path.<br>
     *
     */
    public List<String> getVocabRuleValues(String iElementName, String iPath) {
        log.debug("getVocabRuleValues()");

        log.debug("    iElementName coming in is " + iElementName);
        log.debug("    iPath coming in is " + iPath);

        List<Node> ruleNodeList = new ArrayList<Node>();
        List<String> vocabList = new ArrayList<String>();

        if (mRulesDocument != null) {
            log.debug("mRulesDocument != null");

            ruleNodeList = retrieveVocabRuleElements(iElementName, iPath, "vocab");

            int numVocabularies = ruleNodeList.size();

            if (numVocabularies != 0) {
                // loop through vocabulary nodes to retrieve value and add them
                // to the string List
                for (int i = 0; i < numVocabularies; i++) {
                    vocabList.add(getTaggedData((ruleNodeList.get(i))));
                }
            } else {
                log.debug("ruleNode is null - rules not found");
            }
        } else {
            log.error("Can not continue validation of rules, doc is null");
        }
        log.debug("getVocabRuleValues()");

        return vocabList;
    }

    /**
     * Creates a RulesManager to produce a DOM of the rules for the specified
     * Metadata/Content Package Application Profile.<br>
     *
     * @param iApplicationProfileType  The application profile rules document 
     * to be read in:
     *        <ul>
     *           <li><code>adlreg</code></li>
     *        </ul> 
     * 
     * @return boolean - a flag is returned describing if the rules have been 
     * read in successfully.  True implies that there were no problems and the 
     * XML rules exist as a DOM, false implies problems occured and application
     * profile checking cannot continue.  
     * 
     */
    public boolean readInRules(String iApplicationProfileType) {
        log.debug("readInRules()");
        log.debug("      iApplicationProfileType coming in is " + iApplicationProfileType);

        boolean result = true;

        // create an DOMRules object to provide the dom of rules
        DOMRulesCreator dom = new DOMRulesCreator(iApplicationProfileType, mValidatorType);

        Document rules = dom.provideRules();

        if (rules != null) {
            mRulesDocument = rules;
            log.debug("root element mRulesDoc = " + ((Node) mRulesDocument.getDocumentElement()).getNodeName());
        } else {
            log.error("Problem parsing XML rules");
            result = false;
        }
        log.debug("readInRules()");
        return result;
    }

    /**
     * Retrieves the actual attrib rule node being searched for.
     *
     * @param iElementName Name of the element we are looking for rules for
     *
     * @param iPath Path of the element we are looking for
     *
     * @param iRuleName Rule we are looking for
     *
     * @param iAttribName Name of the attrib element we are looking for
     *
     * @return Node:  attrib's rule element being searched for
     */
    private Node retrieveAttribRuleElement(String iElementName, String iPath, String iRuleName,
            String iAttribName) {
        log.debug("retrieveAttribRuleElement()");
        Node resultNode = null;

        Node rootRulesNode = mRulesDocument.getDocumentElement();
        NodeList kids = rootRulesNode.getChildNodes();
        int numKids = kids.getLength();

        Node currentElementNode;
        String nodeName;
        String path;

        for (int i = 0; i < numKids; i++) {
            // traverse the element nodes and find the one with the correct
            // name and path attribute value
            currentElementNode = kids.item(i);
            nodeName = getAttribute(currentElementNode, "name");
            log.debug("currentElementNode's name is " + nodeName);

            path = getAttribute(currentElementNode, "path");
            log.debug("currentElementNode's path is " + path);

            if (nodeName.equals(iElementName) && path.equals(iPath)) {
                // traverse the child nodes and find the one with the attribute
                // elements
                NodeList currentElementNodeKids = currentElementNode.getChildNodes();
                int numCurrentNodeKids = currentElementNodeKids.getLength();
                log.debug("numCurrentNodeKids is " + numCurrentNodeKids);

                Node attributeNode;
                String attributeNodeName;
                for (int j = 0; j < numCurrentNodeKids; j++) {
                    // traverse the attribute nodes and find the one with
                    // the name that we want
                    attributeNode = currentElementNodeKids.item(j);
                    attributeNodeName = attributeNode.getNodeName();
                    log.debug("attributeNodeName is " + attributeNodeName);

                    if (attributeNodeName.equals("attrib")) {
                        String attributeName = getAttribute(attributeNode, "name");

                        if (attributeName.equals(iAttribName)) {
                            log.debug("Attribute rule found for " + attributeName);

                            // traverse the children of the specified attribute and
                            // get the specified rule
                            NodeList attributeNodeKids = attributeNode.getChildNodes();
                            int numAttributeNodeKids = attributeNodeKids.getLength();

                            Node ruleNode;
                            String ruleNodeName;

                            for (int k = 0; k < numAttributeNodeKids; k++) {
                                ruleNode = attributeNodeKids.item(k);
                                ruleNodeName = ruleNode.getNodeName();
                                log.debug("Found the " + ruleNodeName + " attribute");

                                if (ruleNodeName.equals(iRuleName)) {
                                    log.debug("Found the " + iRuleName + " rule");
                                    resultNode = ruleNode;
                                    break;
                                }
                            }

                            break;
                        }
                    }
                }

                break;
            }
        }
        log.debug("retrieveAttribRuleElement()");

        return resultNode;
    }

    /**
     * Retrieves a List of the vocabulary rules for the attribute element
     * being searched for.
     *
     * @param iElementName Name of the element we are looking for rules for
     *
     * @param iPath Path of the element we are looking for
     *
     * @param iRuleName Rule being tested
     *
     * @param iAttribName Name of the attrib element we are looking for
     *
     * @return List: containing vocabulary for the attrib element being
     * searched for
     */
    private List<Node> retrieveAttribVocabRuleElements(String iElementName, String iPath, String iRuleName,
            String iAttribName) {
        log.debug("retrieveAttribVocabRuleElements()");

        List<Node> resultList = new ArrayList<Node>();

        Node rootRulesNode = mRulesDocument.getDocumentElement();
        NodeList kids = rootRulesNode.getChildNodes();
        int numKids = kids.getLength();

        Node currentElementNode;
        String nodeName;
        String path;

        for (int i = 0; i < numKids; i++) {
            // traverse the element nodes and find the one with the correct
            // name and path attribute value
            currentElementNode = kids.item(i);
            nodeName = getAttribute(currentElementNode, "name");
            log.debug("currentElementNode's name is " + nodeName);

            path = getAttribute(currentElementNode, "path");
            log.debug("currentElementNode's path is " + path);

            if (nodeName.equals(iElementName) && path.equals(iPath)) {
                // traverse the child nodes and find the one with the attribute
                // elements
                NodeList currentElementNodeKids = currentElementNode.getChildNodes();
                int numCurrentNodeKids = currentElementNodeKids.getLength();
                log.debug("numCurrentNodeKids is " + numCurrentNodeKids);

                Node attributeNode;
                String attributeNodeName;
                for (int j = 0; j < numCurrentNodeKids; j++) {
                    // traverse the attribute nodes and find the one with
                    // the name that we want
                    attributeNode = currentElementNodeKids.item(j);
                    attributeNodeName = attributeNode.getNodeName();
                    log.debug("attributeNodeName is " + attributeNodeName);

                    if (attributeNodeName.equals("attrib")) {
                        String attributeName = getAttribute(attributeNode, "name");

                        if (attributeName.equals(iAttribName)) {
                            log.debug("Attribute rule found for " + attributeName);

                            // traverse the children of the specified attribute and
                            // get the specified rule
                            NodeList attributeNodeKids = attributeNode.getChildNodes();
                            int numAttributeNodeKids = attributeNodeKids.getLength();

                            Node ruleNode;
                            String ruleNodeName;

                            for (int k = 0; k < numAttributeNodeKids; k++) {
                                ruleNode = attributeNodeKids.item(k);
                                ruleNodeName = ruleNode.getNodeName();
                                log.debug("Found the " + ruleNodeName + " attribute");

                                if (ruleNodeName.equals(iRuleName) && iRuleName.equals("vocab")) {
                                    log.debug("Found the " + iRuleName + " rule");
                                    resultList.add(ruleNode);
                                }
                            }

                            break;
                        }
                    }
                }

                break;
            }
        }
        log.debug("retrieveAttribVocabRuleElements()");

        return resultList;
    }

    /**
     * Retrieves the actual rule node being searched for.
     *
     * @param iElementName Name of the element we are looking for rules for
     *
     * @param iPath Path of the element we are looking for
     *
     * @param iRuleName Rule we are looking for
     *
     * @return Node The node containing the element being searched for
     */
    private Node retrieveRuleElement(String iElementName, String iPath, String iRuleName) {
        log.debug("retrieveRuleElement()");

        Node resultNode = null;

        Node rootRulesNode = mRulesDocument.getDocumentElement();
        NodeList kids = rootRulesNode.getChildNodes();
        int numKids = kids.getLength();

        Node currentElementNode;
        String nodeName;
        String path;

        for (int i = 0; i < numKids; i++) {
            // traverse the element nodes and find the one with the correct
            // name and path attribute value
            currentElementNode = kids.item(i);
            nodeName = getAttribute(currentElementNode, "name");
            log.debug("currentElementNode's name is " + nodeName);

            path = getAttribute(currentElementNode, "path");
            log.debug("currentElementNode's path is " + path);

            if (nodeName.equals(iElementName) && path.equals(iPath)) {
                // traverse the child nodes and find the one with the attribute
                // elements
                NodeList currentElementNodeKids = currentElementNode.getChildNodes();
                int numCurrentNodeKids = currentElementNodeKids.getLength();
                log.debug("numCurrentNodeKids is " + numCurrentNodeKids);

                Node ruleNode;
                String ruleNodeName;
                for (int j = 0; j < numCurrentNodeKids; j++) {
                    // traverse the attribute nodes and find the one with
                    // the name that we want
                    ruleNode = currentElementNodeKids.item(j);
                    ruleNodeName = ruleNode.getNodeName();
                    log.debug("ruleNodeName is " + ruleNodeName);

                    if (iRuleName.equals("min") || iRuleName.equals("max") || iRuleName.equals("spm")
                            || iRuleName.equals("datatype")) {
                        if (ruleNodeName.equals(iRuleName)) {
                            resultNode = ruleNode;
                            break;
                        }
                    } else {
                        log.error("The rule searched for is not available");
                    }
                }
                break;
            }
        }
        log.debug("retrieveRuleElement()");

        return resultNode;
    }

    /**
     * Retrieves a List of the vocabulary rule node being searched for.
     *
     * @param iElementName Name of the element we are looking for rules for
     *
     * @param iPath Path of the element we are looking for
     *
     * @param iRuleName Rule we are looking for
     *
     * @return List Containing the valid vocabularies for the element being
     * tested
     */
    private List<Node> retrieveVocabRuleElements(String iElementName, String iPath, String iRuleName) {
        log.debug("retrieveVocabRuleElements()");

        List<Node> resultList = new ArrayList<Node>();

        Node rootRulesNode = mRulesDocument.getDocumentElement();
        NodeList kids = rootRulesNode.getChildNodes();
        int numKids = kids.getLength();

        Node currentElementNode;
        String nodeName;
        String path;

        for (int i = 0; i < numKids; i++) {
            // traverse the element nodes and find the one with the correct
            // name and path attribute value
            currentElementNode = kids.item(i);
            nodeName = getAttribute(currentElementNode, "name");
            log.debug("currentElementNode's name is " + nodeName);

            path = getAttribute(currentElementNode, "path");
            log.debug("currentElementNode's path is " + path);

            if (nodeName.equals(iElementName) && path.equals(iPath)) {
                // traverse the child nodes and find the one with the attribute
                // elements
                NodeList currentElementNodeKids = currentElementNode.getChildNodes();
                int numCurrentNodeKids = currentElementNodeKids.getLength();
                log.debug("numCurrentNodeKids is " + numCurrentNodeKids);

                Node ruleNode;
                String ruleNodeName;
                for (int j = 0; j < numCurrentNodeKids; j++) {
                    // traverse the child nodes and find the one with
                    // the name that we want
                    ruleNode = currentElementNodeKids.item(j);
                    ruleNodeName = ruleNode.getNodeName();
                    log.debug("ruleNodeName is " + ruleNodeName);

                    if (iRuleName.equals("vocab")) {
                        if (ruleNodeName.equals(iRuleName)) {
                            resultList.add(ruleNode);
                        }
                    }
                }
                break;
            }
        }
        log.debug("retrieveVocabRuleElements()");

        return resultList;
    }

    /**
     * Sorts the elements attributes.
     *
     * @param iAttrs list of attributes to be sorted
     *
     * @return sorted array of attributes
     */
    protected Attr[] sortAttributes(NamedNodeMap iAttrs) {
        int len = (iAttrs != null) ? iAttrs.getLength() : 0;
        Attr array[] = new Attr[len];
        for (int i = 0; i < len; i++) {
            array[i] = (Attr) iAttrs.item(i);
        }
        for (int i = 0; i < len - 1; i++) {
            String name = array[i].getLocalName();
            int index = i;
            for (int j = i + 1; j < len; j++) {
                String curName = array[j].getLocalName();
                if (curName.compareTo(name) < 0) {
                    name = curName;
                    index = j;
                }
            }
            if (index != i) {
                Attr temp = array[i];
                array[i] = array[index];
                array[index] = temp;
            }
        }

        return array;
    }
}