Package org.olat.modules.scorm.manager

Source Code of org.olat.modules.scorm.manager.ScormManager

/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/

package org.olat.modules.scorm.manager;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

import org.jdom.Element;
import org.olat.core.logging.OLATRuntimeException;
import org.olat.modules.scorm.ISettingsHandler;
import org.olat.modules.scorm.contentpackaging.NavigationViewer;
import org.olat.modules.scorm.server.sequence.SequenceManager;

import uk.ac.reload.moonunit.contentpackaging.CP_Core;

/**
* Initial Date: 13.06.2005 <br>
* @author guido
*/
public class ScormManager {
  /**
   * The package name Note - this should not really be static - this assumes
   * you're only ever going to have one package open at a time.
   */
  public static String PACKAGE_NAME;

  /**
   * instance of the navigationviewer - used to lookup values/elements from the
   * manifest.
   */
  protected NavigationViewer _navViewer;

  /**
   * A boolean to tell us if the player should show the tree widget
   */
  private boolean _showTreeWidget;

  /**
   * A boolean to tell us if the player should show the next and prev navigation
   */
  private boolean _showNavigation;

  /**
   * Whether to use auto progression thru the package
   */
  private boolean _autoProgression;

  /**
   * The manager's instance of the scorm sequence manager - used for sequencing
   * and prerequisites, and cmi updating models
   */
  private SequenceManager _sequence;

  /**
   * boolean value used to flag that navigation nav file has been found
   */
  private boolean _error_found;

  private boolean _ReloadNoItemFoundExceptionFlag = true;

  /**
   * An array of javascrtip string info which the tree widget will use
   */
  private String[] _javascriptStrings;

  /**
   * Keep hold of the default org (JDOM) element
   */
  private Element _defaultorg;
  private List organizationElements;

  /**
   * A count of organizations (should really only be one for the tree widget)
   */
  private int _orgCount = -1;

  /**
   * Used to keep track of how many items there are in a organization (this is
   * array based, so initially set to -1)
   */
  private int _itemCount = -1;

  /**
   * Default constructor
   */
  public ScormManager() {
  // empty constructor
  }

  /**
   * Comment for <code>scormFileHandler</code>
   */
  private ISettingsHandler scormSettingsHandler;

  /**
   * Alternate constructor - used to pass the the package name (i.e. - used to
   * construct a path to disk and find the files needed. It also allows us to
   * specify if we want to show the tree widget and the next and previous
   * buttons in the navigation
   *
   * @param packagePath
   * @param repoId
   * @param courseId
   * @param userPath
   * @param username
   * @param userid
   * @param showTreeWidget
   * @param showNavigation
   * @param autoProgression
   * @param lesson_mode
   * @param credit_mode
   */

  public ScormManager(String packagePath, boolean showTreeWidget, boolean showNavigation, boolean autoProgression, ISettingsHandler settings) {
    this.scormSettingsHandler = settings;
    _error_found = false;
    PACKAGE_NAME = packagePath;
    _showNavigation = showNavigation;
    _showTreeWidget = showTreeWidget;
    _autoProgression = autoProgression;
    init();
  }

  /**
   *
   */
  private void init() {
    // Make sure its there
    if (scormSettingsHandler.getManifestFile().exists()) {
      try {
        _navViewer = new NavigationViewer(scormSettingsHandler);
      } catch (Exception ex) {
        throw new OLATRuntimeException(ScormManager.class, "Could not load manifest",ex);
      }
      // Package Links - use a clone so we can add referenced elements
      Element manifestRoot = (Element) _navViewer.getRootElement().clone();
      // now get the organizations node
      Element orgs = manifestRoot.getChild(CP_Core.ORGANIZATIONS, manifestRoot.getNamespace());
      Element[] tmp = _navViewer.getOrganizationList();
      organizationElements = new LinkedList();
      for (int i = 0; i < tmp.length; ++i) {
        organizationElements.add(tmp[i]);
      }
      // remember the default organization
      _defaultorg = _navViewer.getDefaultOrgElement(orgs);
      // NO orgs, so cant play - flag it
      if (_defaultorg == null) {
        _ReloadNoItemFoundExceptionFlag = false;
      } else {
        _sequence = new SequenceManager(_defaultorg.getAttributeValue(CP_Core.IDENTIFIER), scormSettingsHandler);
        // it exists so try to load it...
        try {
          initialize();
        } catch (Exception ex) {
          _error_found = true;
          throw new OLATRuntimeException(ScormManager.class, "Could not initialise manifest",ex);
        }
      } //
    } else {
      // problems if we cannot find the nav file...
      _error_found = true;
    }

  }

  /**
   * Accessor method to obtain the array of javascrtip strings needed by the
   * tree widget
   *
   * @return String
   */
  public String[] getJavascriptStrings() {
    return _javascriptStrings;
  }

  /**
   * Accesor method for the sequencer
   *
   * @return SequenceManager
   */
  public SequenceManager getSequence() {
    return _sequence;
  }

  /**
   * Accessor method - should we show the tree or not?
   *
   * @return boolean
   */
  public boolean isTreeVisible() {
    return _showTreeWidget;
  }

  /**
   * Accessor method - should we show the navigation or not?
   *
   * @return boolean
   */
  public boolean isNavVisible() {
    return _showNavigation;
  }

  /**
   * Accessor method - boolean to use auto progression of items in player
   *
   * @return boolean
   */
  public boolean isAutoProgressionEnabled() {
    return _autoProgression;
  }

  /**
   * A method to do some initialising before we actually play the package. Here
   * we get the default organization and then pass that to a method which will
   * parse that organization (JDOM) and figure out what we need, in terms of
   * items, sequence, prerequisites, etc
   */
  public void initialize() {
    if (_navViewer.getDocument() == null) { return; }
    _javascriptStrings = parse(false);
  }

  /**
   * A method to start the parse of the manifest and write the javascript
   * strings which the tree widget needs and also to populate the sequencer
   *
   * @param useRelativePaths
   * @return String[]
   */
  protected String[] parse(boolean useRelativePaths) {
    // New Vector
    Vector v = new Vector();
    writePackageSettings(v, "packageName", getProjectName());
    // now call createNavLinks() which should interrogate the org/item structure
    createNavLinksForAllOranizations(v, "menu", useRelativePaths);
    // Convert Vector to String array
    String[] javascriptStrings = new String[v.size()];
    v.copyInto(javascriptStrings);
    return javascriptStrings;
  }

  protected void createNavLinksForAllOranizations(Vector javascriptStrings, String menuParent, boolean useRelativePaths) {
    _itemCount = -1;
    for (int i = 0; i < organizationElements.size(); ++i) {
      createNavLinks(javascriptStrings, (Element)organizationElements.get(i), menuParent, useRelativePaths);
    }
  }
 
  /**
   * Recursive method to find all of the javascript strings (item info) and
   * populate the sequencer
   *
   * @param javascriptStrings
   * @param element
   * @param menuParent
   * @param useRelativePaths
   */
  protected void createNavLinks(Vector javascriptStrings, Element element, String menuParent, boolean useRelativePaths) {
    String name = element.getName();
    // ORGANIZATION
    if (name.equals(CP_Core.ORGANIZATION) && _navViewer.isDocumentNamespace(element)) {
      ++_orgCount;
      String orgId = element.getAttributeValue(CP_Core.IDENTIFIER);
      menuParent = "menu";
      String title = "Organization";
      // Display Title if there is one
      Element titleElement = element.getChild(CP_Core.TITLE, element.getNamespace());
      if (titleElement != null) {
        if (!titleElement.getText().equals("")) title = titleElement.getText();
      }
      // find out if this the default organization...
      String _defaultOrganization = _defaultorg.getAttributeValue(CP_Core.IDENTIFIER);
      if (_defaultOrganization != null) {
        if (_defaultOrganization.equals(orgId)) {
          writePackageSettings(javascriptStrings, "_defaultOrg", _orgCount);
        }
      }
      writeOrganization(javascriptStrings, title, orgId);
    }
    // ITEM
    else if (name.equals(CP_Core.ITEM) && _navViewer.isDocumentNamespace(element)) {
      ++_itemCount;
      String itemId = element.getAttributeValue(CP_Core.IDENTIFIER);
      String hyperLink = "";
      String url = "";
      String scoType = "";
      // Display Title if there is one
      String title = "Item";
      Element titleElement = element.getChild(CP_Core.TITLE, element.getNamespace());
      if (titleElement != null) {
        if (!titleElement.getText().equals("")) title = titleElement.getText();
      }
      // check to see that the isvisible attribute is not set to false...
      String isVisibleAttrib = element.getAttributeValue(CP_Core.ISVISIBLE);
      if (isVisibleAttrib != null) {
        if (isVisibleAttrib.equals("false")) {
          title = "* hidden";
        }
      }
      // What does this Item reference?
      Element ref_element = _navViewer.getScormCore().getReferencedElement(element);
      String prerequisites = "";
      if (ref_element != null) {
        String ref_name = ref_element.getName();
        // A RESOURCE
        if (ref_name.equals(CP_Core.RESOURCE)) {
          scoType = _navViewer.findScoType(element);
          // Relative path for export - Note the "../" is relative to where the
          // Nav file is!
          if (useRelativePaths) {
            url = _navViewer.getScormCore().getRelativeURL(element);
            // Only if local path add relative bit
            if (isExternalURL(url) == false) {
              url = "../" + url;
            }
          }
          // Absolute Paths for Previewing in-situ
          else {
            String turl = _navViewer.getLaunch(element);
            url = turl;
          }
          if (url != null) {
            hyperLink = url;
            if (!title.equals("* hidden")) {
              prerequisites = _navViewer.getPrerequisites(element);
              if (prerequisites == null) {
                prerequisites = "";
              }
            }
          }
        }
        // A sub-MANIFEST
        else if (ref_name.equals(CP_Core.MANIFEST)) {
          hyperLink = "javascript:void(0)";
          // Get ORGANIZATIONS Element
          Element orgsElement = ref_element.getChild(CP_Core.ORGANIZATIONS, ref_element.getNamespace());
          // Now we have to get the default ORGANIZATION
          if (orgsElement != null) ref_element = _navViewer.getScormCore().getDefaultOrganization(orgsElement);
          // Get the children of the referenced <organization> element and graft
          // clones
          if (ref_element != null) {
            Iterator it = ref_element.getChildren().iterator();
            while (it.hasNext()) {
              Element ref_child = (Element) it.next();
              element.addContent((Element) ref_child.clone());
            }
          }
        }
      } else {
        hyperLink = "javascript:void(0)";
      }
      // System.out.println("adding to sequencer:"+ itemId + " " + hyperLink+ "
      // " + _itemCount+ " " + scoType+ " " +title+ " " + prerequisites);
      _sequence.addNewItem(itemId, hyperLink, _itemCount, scoType, title, prerequisites);
      writeItem(javascriptStrings, title, hyperLink, itemId, menuParent);
      menuParent = itemId;
    }
    // round we go again...
    Iterator it = element.getChildren().iterator();
    while (it.hasNext()) {
      Element child = (Element) it.next();
      createNavLinks(javascriptStrings, child, menuParent, useRelativePaths);
    }
  }

  /**
   * Writes "top level" CPAPI settings to the vector of javascript code.
   *
   * @param name - the name of the item to set
   * @param value - the value of the item to set (String)
   */
  protected void writePackageSettings(Vector javascriptStrings, String name, String value) {
    javascriptStrings.add("CPAPI." + name + " = \"" + value + "\";");
  }

  /**
   * Writes "top level" CPAPI settings to the vector of javascript code.
   *
   * @param name - the name of the item to set
   * @param value - the value of the item to set (int)
   */
  protected void writePackageSettings(Vector javascriptStrings, String name, int value) {
    javascriptStrings.add("CPAPI." + name + " = " + value + ";");
  }

  /**
   * Writes "organization" CPAPI settings to the vector of javascript code.
   *
   * @param title - the title of this organization
   * @param orgId - the organization identifier
   */
  protected void writeOrganization(Vector javascriptStrings, String title, String orgId) {
    javascriptStrings.add("CPAPI.orgArray(" + _orgCount + ").organizationName = \"" + escapeQuotes(title) + "\";");
    javascriptStrings.add("CPAPI.orgArray(" + _orgCount + ").organizationIdentifier = \"" + orgId + "\";");
  }

  /**
   * Writes "item" CPAPI settings to the vector of javascript code.
   *
   * @param javascriptStrings
   * @param title - the title of this item
   * @param url - the launch url of this item
   * @param itemId - the item identifier
   * @param parentMenu - the tree node to attach this to.
   */
  protected void writeItem(Vector javascriptStrings, String title, String url, String itemId, String parentMenu) {
    // the javscript tree widget doesn't like hyphens, so replace them with
    // underscores...
    parentMenu = parentMenu.replace('-', '_');
    // add the item...
    javascriptStrings.add("CPAPI.orgArray(" + _orgCount + ").itemArray(" + _itemCount + ").itemTitle = \"" + escapeQuotes(title) + "\";");
    javascriptStrings.add("CPAPI.orgArray(" + _orgCount + ").itemArray(" + _itemCount + ").itemIdentifier = \"" + itemId + "\";");
    javascriptStrings.add("CPAPI.orgArray(" + _orgCount + ").itemArray(" + _itemCount + ").itemParent = \"" + parentMenu + "\";");
    javascriptStrings.add("CPAPI.orgArray(" + _orgCount + ").itemArray(" + _itemCount + ").itemHyper = \"" + url + "\";");
  }

  /**
   * Utility method to escape all string delimiters found with a string
   *
   * @param inputString - the string to escape
   * @return - the string with escaped quotes (in javascript format)
   */
  protected String escapeQuotes(String inputString) {
    inputString = inputString.replaceAll("'", "\\\\\\\\'"); // replace a single
    // quote with \\'
    inputString = inputString.replaceAll("\"", "\\\\\""); // replace a double
    // quote with \"
    return inputString;
  }

  /**
   * Accessor method - get the project name
   *
   * @return - a string
   */
  public String getProjectName() {
    return PACKAGE_NAME;
  }

  /**
   * @return Returns the _errorfound.
   */
  public boolean isErrorFound() {
    return _error_found;
  }

  public boolean hasItemsFound() {
    return this._ReloadNoItemFoundExceptionFlag;
  }

  /**
   * @param href The href to parse
   * @return true if href is an external URL
   */
  public static boolean isExternalURL(String href) {
    if (href != null) {
      href = href.toLowerCase();
      return href.startsWith("http") || href.startsWith("www") || href.startsWith("ftp:");
    }
    return false;
  }
}
TOP

Related Classes of org.olat.modules.scorm.manager.ScormManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.