org.adl.samplerte.server.LMSManifestHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.adl.samplerte.server.LMSManifestHandler.java

Source

/*******************************************************************************
 ** 
 ** Filename:  LMSManifestHandler.java
 **
 ** File Description:  This file extends from CPDOMParser.  It uses the parser
 **                    in a way unique to the Sample RTE.  All relevant data
 **                    from the manifest file is written to a corresponding
 **                    database after it is accessed.
 **
 ** Author:  ADLI Project
 **
 ** Company Name: CTC
 **
 ** Module/Package Name: org.adl.lms.server
 ** Module/Package Description:
 **
 ** Design Issues:
 **
 ** Implementation Issues:
 ** Known Problems:
 ** Side Effects:
 **
 ** References:  SCORM
 **
 *******************************************************************************
 **
 ** Concurrent Technologies Corporation (CTC) 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 CTC.
 **
 ** 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.  CTC 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 CTC  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 CTC HAS BEEN ADVISED OF THE POSSIBILITY
 ** OF SUCH DAMAGES. 
 **
 *******************************************************************************
 **
 ** Date Changed   Author of Change  Reason for Changes
 ** ------------   ----------------  -------------------------------------------
 **
 *******************************************************************************/
package org.adl.samplerte.server;

// ADL imports
import java.io.IOException;
import java.net.URLDecoder;
import java.sql.Timestamp;
import java.util.List;
import java.util.Vector;

import javax.annotation.Resource;

import org.adl.parsers.dom.ADLItem;
import org.adl.parsers.dom.ADLOrganizations;
import org.adl.parsers.dom.CPDOMParser;
import org.adl.util.debug.DebugIndicator;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.w3c.dom.Attr;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.scorm.action.ActionSupport;
import com.scorm.service.CourseinfoService;
import com.scorm.service.ScoinfoService;
import com.scorm.utils.UserCommon;
import com.scorm.vo.Courseinfo;
import com.scorm.vo.Scoinfo;
import com.scorm.vo.Userinfo;

@Scope(value = "prototype")
@Component(value = "lmsManifestHandler")
public class LMSManifestHandler extends CPDOMParser {

    @Resource(name = "scoinfoService")
    private ScoinfoService scoinfoService;

    @Resource(name = "courseinfoService")
    private CourseinfoService courseinfoService;

    protected Vector items;
    private Vector tempItemList;
    protected InputSource sourceToParse;
    protected String courseTitle;
    protected String courseDir;
    protected String courseID;
    protected String control;
    protected String isTest;

    /**************************************************************************
     ** 
     ** Method: LMSManifestHandler() Input: None
     ** 
     ** Output: None
     ** 
     ** Description: Default Constructor.
     ** 
     ***************************************************************************/
    public LMSManifestHandler() {
        super();
        tempItemList = new Vector();
        items = new Vector();
        courseTitle = "";
        courseDir = "";
        courseID = "";
        control = "";
    }

    /****************************************************************************
     ** 
     ** Method: processManifest() Input: None Output: boolean - Whether or not
     * the method was successful Description: This method initiates the RTE
     * import/parsing of a manifest file from a PIF content package.
     ** 
     ** Side Effects: none
     ** 
     ****************************************************************************/
    public boolean processManifest() {
        boolean valid = false;
        if (DebugIndicator.ON) {
            System.out.println("Entering LMSManifestHandler::processManifest()");
        }

        try {
            // Parse the file
            parse(sourceToParse);

            if (DebugIndicator.ON) {
                System.out.println("Document parsing complete.");
            }
            System.out.println("1----document=" + document);
            document = getDocument();
            System.out.println("2----document=" + document);
            valid = true;

            // Call process content
            processContent();
        } catch (SAXException se) {
            String message = "Parser threw a SAXException.";
            System.out.println(message);
        } catch (IOException ioe) {
            String message = "Parser threw a IOException.";
            System.out.println(message);
        }

        if (DebugIndicator.ON) {
            System.out.println("Exiting LMSManifestHandler::processManifest()");
        }

        // Write to the corresponding database
        updateDB();
        // Return boolean signifying whether or not the parsing was successful
        return valid;
    }

    /****************************************************************************
     ** 
     ** Method: processContent() Input: none Output: boolean - Whether the method
     * was successful or not. Description: This method starts at the root node
     * and then calls calls fillManifest which populates the parser structure.
     ** 
     ** Side Effects: none
     ** 
     ***************************************************************************/
    public boolean processContent() {
        if (DebugIndicator.ON) {
            System.out.println("*** LMSManifestHandler::processContent() ***");
        }

        // boolean that signifies whether or not the method call was successful
        boolean result = true;

        if (DebugIndicator.ON) {
            if (document == null) {
                System.out.println("the document is null");
            }
        }
        System.out.println("-------document=" + document + "|---");
        // Get the root node of the imsmanifest <manifest>
        Node contentNode = document.getDocumentElement();

        // Get the children of the root node
        NodeList contentChildren = contentNode.getChildNodes();

        if (DebugIndicator.ON) {
            System.out.println("*** NODE: " + contentNode.getNodeName());
            System.out.println("*** Children - " + contentChildren.getLength() + " ***");
        }

        // Call fillManifest(). This will fill the parser structure
        this.manifest.fillManifest(contentNode);

        // Set the control attribute
        // *************************************************
        // This is proprietary in version 1.2 of the RTE
        // This will change!
        // *************************************************
        this.setSequence();

        // Uses the newly populated structure to populate the
        // items Vector.
        this.items = this.getItemList();

        // Get resources and compare w/ the item Vector
        for (int i = 0; i < contentChildren.getLength(); i++) {
            Node currentNode = contentChildren.item(i);

            // Make sure this is an "element node"
            if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
                // Move to the resources element to process the resources
                if (currentNode.getNodeName().equalsIgnoreCase("resources")) {
                    if (DebugIndicator.ON) {
                        System.out.println("*** Found Current Node: " + currentNode.getNodeName());
                    }

                    // process the Resources section.
                    result = processResources(currentNode);
                    if (result == false) {
                        break;
                    }
                }

            }
        }

        if (DebugIndicator.ON) {
            System.out.println("*** Exiting LMSManifestHandler::processContent() ***");
            System.out.println("*** Returning: " + result);
        }
        return result;
    }

    /****************************************************************************
     ** 
     ** Method: processResources Input: Node resourcesNode - The <resources> node
     * from the imsmanfest file Output: Description: This method populates the
     * resources section of the parser structure.
     ** 
     ** Side Effects: none
     ** 
     ***************************************************************************/
    public boolean processResources(Node resourcesNode) {

        boolean result = true;
        int level = 1;

        if (DebugIndicator.ON) {
            System.out.println("******  LMSManifestHandler:processResources  *********");
        }

        if (document == null) {
            System.out.println("the document is null");
        }

        // Get the children of the resources node
        NodeList resourcesChildren = resourcesNode.getChildNodes();

        if (DebugIndicator.ON) {
            System.out.println("*** NODE: " + resourcesNode.getNodeName());
            System.out.println("*** Children - " + resourcesChildren.getLength() + " ***");
        }

        // Find the resource node(s)
        for (int i = 0; i < resourcesChildren.getLength(); i++) {
            Node currentNode = resourcesChildren.item(i);

            // Make sure this is an "element node"
            if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
                if (currentNode.getNodeName().equalsIgnoreCase("resource")) {
                    if (DebugIndicator.ON) {
                        System.out.println("*** Found Current Node: " + currentNode.getNodeName());
                    }

                    result = processResource(currentNode);
                    if (result == false) {
                        break;
                    }
                }
            }
        }

        if (DebugIndicator.ON) {
            System.out.println("*** Exiting LMSManifestHandler::processResources() ***");
            System.out.println("*** Returning: " + result);
        }

        return result;
    }

    /****************************************************************************
     ** 
     ** Method: processResource() Input: Node resourceNode - A <resource> node
     * from the imsmanifest file Output: Description: This method populates the
     * resource section of the parser object.
     ** 
     ** Side Effects: none
     ** 
     ***************************************************************************/
    public boolean processResource(Node resourceNode) {
        boolean result = true;

        if (DebugIndicator.ON) {
            System.out.println("******  LMSManifestHandler:processResource  *********");
        }

        String id = getAttribute(resourceNode, "identifier");
        String scormType = getAttribute(resourceNode, "adlcp:scormtype");
        String type = getAttribute(resourceNode, "type");
        String href = getAttribute(resourceNode, "href");

        updateItemList(id, scormType, type, href);

        if (DebugIndicator.ON) {
            System.out.println("*** Exiting LMSManifestHandler::processResource() ***");
            System.out.println("*** Returning: " + result);
        }

        return result;

    }

    /****************************************************************************
     ** 
     ** Method: updateItemList Input: String id - the identifier of the item
     * String scormType - the scormtype of the item (or reference) String type -
     * the type attribute String href - the href location Output: Description:
     * This method adds the launch location to the item vector. The launch is
     * not part of the <item> element, so this method compares the identifier
     * and identifierref and when a match is found, the item section of the
     * parser object is populated with the resource launch location. This is
     * done only for convenience.
     ** 
     ** Side Effects: none
     ** 
     ***************************************************************************/
    public void updateItemList(String id, String scormType, String type, String href) {
        if (DebugIndicator.ON) {
            System.out.println("******  LMSManifestHandler:updateItemList  *********");
        }

        ADLItem tempItem = new ADLItem();

        // Loop throught the item vector checking the identfierref with the
        // identifier of the resource. If they match, update the item and exit
        for (int i = 0; i < items.size(); i++) {
            tempItem = (org.adl.parsers.dom.ADLItem) this.items.elementAt(i);
            String idref = tempItem.getIdentifierref();

            if (idref.equals(id)) {
                if (DebugIndicator.ON) {
                    System.out.println("****** !!  Found Matching Resource  !!  *****");
                    System.out.println("i is:" + i + " -- Items size is" + items.size());
                }

                if (type != null && !type.equals("")) {
                    tempItem.setType(type);
                }
                if (scormType != null && !type.equals("")) {
                    tempItem.setScormType(scormType);
                }
                if (href != null && !href.equals("")) {
                    tempItem.setLaunchLocation(href);
                }
                items.removeElementAt(i);
                items.insertElementAt(tempItem, i);
            }
        }

        if (DebugIndicator.ON) {
            System.out.println("****** Exiting - LMSManifestHandler:updateItemList  *********");
        }

    }

    /****************************************************************************
     ** 
     ** Method: getCourseID() Input: none Output: String - this course id.
     * Description: This is a getter method on the courseID member.
     ** 
     ****************************************************************************/
    public String getCourseID() {
        return this.courseID;
    }

    /****************************************************************************
     ** 
     ** Method: getOrgsCopy() Input: none Output: ADLOrganizations Description:
     * This method was developed anticipating sequencing for version 1.3. This
     * method will return the entire course <organization> information. This
     * will include all sequencing information.
     ** 
     ****************************************************************************/
    public ADLOrganizations getOrgsCopy() {
        return this.manifest.getOrganizations();
    }

    /****************************************************************************
     ** 
     ** Method: setSequence() Input: none Output: none Description: This method
     * will be used to set the control type when sequencing is introduced in
     * version 1.3.
     ** 
     ****************************************************************************/
    public void setSequence() {
        if (DebugIndicator.ON) {
            System.out.println("In LMSManifestHandler:setSequence() ");
        }
        // ****************************************************************
        // This is being commented out due to the lack of a sequencing spec
        // in version 1.2. It will be used in the next version
        // ****************************************************************
        // this.control =
        // this.manifest.getOrganizations().getFirstOrg().getSequence().getControl();

        if (DebugIndicator.ON) {
            System.out.println("Control is: " + this.control);
        }
    }

    // Class "Setter" methods
    public void setCourseName(String courseTitle) {
        this.courseTitle = courseTitle;
    }

    public void setControl(String controlType) {
        this.control = controlType;
    }

    public void setFileToParse(InputSource inputStream) {
        this.sourceToParse = inputStream;
    }

    /****************************************************************************
     ** 
     ** Method: updateDB() Input: none Output: none Description: This method
     * takes the relevant information from the populated parser structure and
     * writes it to a related database. This is done so that the JSP coding is
     * more straight forward.
     ** 
     ** Side Effects: none
     ** 
     ***************************************************************************/
    protected void updateDB() {
        if (DebugIndicator.ON) {
            System.out.println("******  LMSManifestHandler:updateDB()  *********");
        }
        try {

            int t = 1;
            List<Scoinfo> list = scoinfoService.findAllScoinfo();
            try {
                System.out.println("----" + list.size());
                if (list != null && list.size() > 0) {
                    t = list.get(list.size() - 1).getScoId() + 1;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            courseID = t + "";

            ADLItem tempItem = new ADLItem();

            // Loop through each item in the course adding it to the
            // database
            for (int i = 0; i < items.size(); i++) {
                tempItem = (org.adl.parsers.dom.ADLItem) items.elementAt(i);

                // Decode the URL before inserting into the database
                URLDecoder urlDecoder = new URLDecoder();
                String alteredLocation = new String();

                // If its external, don't concatenate to the local Web root.
                if ((tempItem.getLaunchLocation().startsWith("http://"))
                        || (tempItem.getLaunchLocation().startsWith("https://"))) {
                    alteredLocation = URLDecoder.decode(tempItem.getLaunchLocation());
                } else {
                    // Create the altered location (with decoded url)
                    alteredLocation = "/scorm/CourseImports/" + courseID + "/"
                            + URLDecoder.decode(tempItem.getLaunchLocation());
                }

                // Insert into the database
                Courseinfo cInfo = null;
                try {
                    System.out.println("courseName=" + courseTitle + "\n-----" + courseinfoService);
                    cInfo = courseinfoService.findByCourseId(Integer.parseInt(courseTitle)).get(0);
                    System.out.println("findCourseName=" + cInfo.getCourseName());
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("error=" + e.getMessage());
                    return;
                }
                System.out.println("------------");
                Timestamp uploadTime = new Timestamp(System.currentTimeMillis());
                System.out.println("isTest=" + isTest);

                Userinfo userinfo = ActionSupport.getSessionUser();
                Scoinfo scoinfo = new Scoinfo(cInfo, tempItem.getTitle(), uploadTime, userinfo.getUserName(),
                        alteredLocation, 0, Integer.parseInt(isTest));
                scoinfoService.saveScoinfo(scoinfo);
                System.out.println("asdfsadf");

            } // Ends looping throught the item list

        } catch (Exception se) {
            if (DebugIndicator.ON) {

                se.printStackTrace();
            }
        }
    }

    /****************************************************************************
     ** 
     ** Method: getAttribute() Input: Node theNode - The current node that was
     * traversed to String the Attribute - The name of the attribute that the
     * value is desired for. Output: Description: This method
     ** 
     ** Side Effects: none
     ** 
     ***************************************************************************/
    protected String getAttribute(Node theNode, String theAttribute) {
        String returnValue = new String();

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

        // now see if the asked for attribute exists and send
        // back the value
        Attr attribute;
        for (int i = 0; i < attrs.length; i++) {
            attribute = attrs[i];

            if (attribute.getName().equals(theAttribute)) {
                returnValue = attribute.getValue();
                break;
            }
        }

        return returnValue;
    }

    /****************************************************************************
     ** 
     ** Method: sortAttributes() Input: NamedNodeMap attrs - The list of
     * attributes Output: Attr[] - Sorted array of attributes Description: This
     * method returns an array of sorted attributes.
     ** 
     ** Side Effects: none
     ** 
     ***************************************************************************/
    protected Attr[] sortAttributes(NamedNodeMap attrs) {
        int len = (attrs != null) ? attrs.getLength() : 0;
        Attr array[] = new Attr[len];
        for (int i = 0; i < len; i++) {
            array[i] = (Attr) attrs.item(i);
        }
        for (int i = 0; i < len - 1; i++) {
            String name = array[i].getNodeName();
            int index = i;
            for (int j = i + 1; j < len; j++) {
                String curName = array[j].getNodeName();
                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);

    }

    /****************************************************************************
     ** 
     ** Method: getSubElement() Input: Node node - The current node that has been
     * traversed to String element - The name of the sub-element that's value is
     * desired. Output: String - The value of the sub-element Description: This
     * method gets the value of a desired sub-element. Side Effects:
     ** 
     ****************************************************************************/
    public String getSubElement(Node node, String element) {
        String value = new String();
        NodeList kids = node.getChildNodes();
        // cycle through all children of node to get the text
        if (kids != null) {
            for (int i = 0; i < kids.getLength(); i++) {
                if (kids.item(i).getNodeType() == Node.ELEMENT_NODE) {
                    // look for the asked for element
                    if (kids.item(i).getNodeName().equalsIgnoreCase(element)) {
                        value = getText(kids.item(i));
                        return value;
                    }
                }
            }
        } else {
            if (DebugIndicator.ON) {
                System.out.println("node has no kids");
            }
        }
        return value;
    }

    /****************************************************************************
     ** 
     ** Method: getText() Input: Node node - The current node Output: String -
     * The text of the desired node. Description: This method gets the child
     * text node of the node that is passed in for input. Side Effects:
     ** 
     ****************************************************************************/
    public String getText(Node node) {
        String value = new String();
        NodeList kids = node.getChildNodes();
        // cycle through all children of node to get the text
        if (kids != null) {
            for (int i = 0; i < kids.getLength(); i++) {
                // make sure we have a text element
                if ((kids.item(i).getNodeType() == Node.TEXT_NODE)
                        || (kids.item(i).getNodeType() == Node.CDATA_SECTION_NODE)) {
                    value = value + kids.item(i).getNodeValue().trim();
                }
            }
        } else {
            if (DebugIndicator.ON) {
                System.out.println("node has no kids");
            }
        }

        return value;
    }

    public String getIsTest() {
        return isTest;
    }

    public void setIsTest(String isTest) {
        this.isTest = isTest;
    }

}