Java tutorial
/********************************************************************************** * * $URL: https://source.sakaiproject.org/contrib/etudes/melete/tags/2.8.2/melete-impl/src/java/org/etudes/component/app/melete/SubSectionUtilImpl.java $ * $Id: SubSectionUtilImpl.java 69867 2010-08-23 21:04:59Z rashmi@etudes.org $ *********************************************************************************** * * Copyright (c) 2008, 2009 Etudes, Inc. * * Portions completed before September 1, 2008 Copyright (c) 2004, 2005, 2006, 2007, 2008 Foothill College, ETUDES Project * * 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. * **********************************************************************************/ package org.etudes.component.app.melete; import java.io.StringWriter; import java.util.List; import java.util.ArrayList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.xml.serialize.OutputFormat; import org.apache.xml.serialize.XMLSerializer; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.DocumentType; import org.dom4j.Element; import org.dom4j.dtd.ElementDecl; import org.dom4j.dtd.AttributeDecl; import org.etudes.api.app.melete.exception.MeleteException; import org.sakaiproject.util.Xml; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /* * Mallika - 6/6/07 - Changed bringOneLevelUp as per ME-424 * Mallika - 6/18/07 - Added check to not add duplicates */ public class SubSectionUtilImpl { private Document subSection4jDOM; private org.w3c.dom.Document subSectionW3CDOM; private Log logger = LogFactory.getLog(SubSectionUtilImpl.class); private List xmlSecList; private org.w3c.dom.Node currParent; private org.w3c.dom.Node currLastSection; public SubSectionUtilImpl() { xmlSecList = new ArrayList(); } private void setInternalDTD() { DocumentType docType = subSection4jDOM.getDocType(); List internalDTDList = new ArrayList(); internalDTDList.add(new ElementDecl("module", "(section+)")); internalDTDList.add(new ElementDecl("section", "(section*)")); internalDTDList.add(new AttributeDecl("section", "id", "ID", "#REQUIRED", "ID")); docType.setInternalDeclarations(internalDTDList); } private void createInitialModule() { subSection4jDOM = DocumentHelper.createDocument(); subSection4jDOM.addDocType("module", "", ""); setInternalDTD(); Element root = subSection4jDOM.addElement("module"); subSection4jDOM.setRootElement(root); } public void addSection(String section_id) { if (subSection4jDOM == null) createInitialModule(); Element rootModule = subSection4jDOM.getRootElement(); Element newSectionElement = rootModule.addElement("section").addAttribute("id", section_id); } public Element addBlankSection() { Element rootModule = subSection4jDOM.getRootElement(); Element newSectionElement = rootModule.addElement("section"); return newSectionElement; } public String storeSubSections() { if (subSection4jDOM == null) return null; return subSection4jDOM.asXML(); } public void addSectiontoList(String sectionsSeqXML, String section_id) { try { // if first section is added if (sectionsSeqXML == null || sectionsSeqXML.length() == 0) { addSection(section_id); return; } // add section to existing list subSection4jDOM = DocumentHelper.parseText(sectionsSeqXML); //The parseText call loses the internal DTD definition, so need to set it again setInternalDTD(); Element thisElement = subSection4jDOM.elementByID(section_id); //This code checks to see if this section id already exists in the xml string if (thisElement == null) addSection(section_id); else logger.debug("Trying to insert duplicate section " + section_id); } catch (DocumentException de) { if (logger.isDebugEnabled()) { logger.debug("error reading subsections xml string" + de.toString()); de.printStackTrace(); } } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("some other error on reading subsections xml string" + ex.toString()); ex.printStackTrace(); } } } private String writeDocumentToString(org.w3c.dom.Document doc) { try { StringWriter sw = new StringWriter(); // Note: using xerces %%% is there a org.w3c.dom way to do this? XMLSerializer s = new XMLSerializer(sw, new OutputFormat("xml", "UTF-8", false)); s.serialize(doc); sw.flush(); return sw.toString(); } catch (Exception any) { logger.warn("writeDocumentToString: " + any.toString()); return null; } } public String MakeSubSection(String sectionsSeqXML, String section_id) throws MeleteException { try { org.w3c.dom.Document subSectionW3CDOM = Xml.readDocumentFromString(sectionsSeqXML); org.w3c.dom.Element root = subSectionW3CDOM.getDocumentElement(); org.w3c.dom.Element indentthisElement = subSectionW3CDOM.getElementById(section_id); // root.selectSingleNode("//*[@id='" + section_id +"']"); if (!indentthisElement.getParentNode().getFirstChild().equals(indentthisElement)) { logger.debug("actually creating subsection"); org.w3c.dom.Node indentParent = indentthisElement.getPreviousSibling(); indentParent.appendChild(indentthisElement); } return writeDocumentToString(subSectionW3CDOM); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.error("some other error in creating sub section" + ex.toString()); ex.printStackTrace(); } throw new MeleteException("indent_right_fail"); } } public String bringOneLevelUp(String sectionsSeqXML, String section_id) throws MeleteException { try { org.w3c.dom.Document subSectionW3CDOM = Xml.readDocumentFromString(sectionsSeqXML); org.w3c.dom.Element root = subSectionW3CDOM.getDocumentElement(); org.w3c.dom.Element bringUpThisElement = subSectionW3CDOM.getElementById(section_id); if (bringUpThisElement == null) { throw new MeleteException("indent_left_fail"); } org.w3c.dom.Node makeSiblingOf = bringUpThisElement.getParentNode(); org.w3c.dom.Node bringUpBeforeThisElement = makeSiblingOf.getNextSibling(); //Clone the node that needs to be moved org.w3c.dom.Node newNode = bringUpThisElement.cloneNode(true); org.w3c.dom.Node nextNode = bringUpThisElement.getNextSibling(); org.w3c.dom.Node prevNode = null; //Iterate through each of the node's siblings and make them its children //In the process, also delete the siblings while (nextNode != null) { org.w3c.dom.Node cNode = nextNode.cloneNode(true); prevNode = nextNode; newNode.appendChild(cNode); nextNode = nextNode.getNextSibling(); prevNode.getParentNode().removeChild(prevNode); } //Insert the new node, inbetween or end of list, takes null or bringUpBeforeThisElement makeSiblingOf.getParentNode().insertBefore(newNode, bringUpBeforeThisElement); //Delete node from original position bringUpThisElement.getParentNode().removeChild(bringUpThisElement); return writeDocumentToString(subSectionW3CDOM); } catch (MeleteException mex) { throw mex; } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.error("some other error on indenting right" + ex.toString()); ex.printStackTrace(); } throw new MeleteException("indent_right_fail"); } } public String deleteSection(String sectionsSeqXML, String section_id) throws MeleteException { try { org.w3c.dom.Document subSectionW3CDOM = Xml.readDocumentFromString(sectionsSeqXML); org.w3c.dom.Element root = subSectionW3CDOM.getDocumentElement(); org.w3c.dom.Element deleteThisElement = subSectionW3CDOM.getElementById(section_id); if (deleteThisElement != null) { org.w3c.dom.Node deleteElementParent = deleteThisElement.getParentNode(); // child nodes becomes children of parent node if (deleteThisElement.hasChildNodes()) { NodeList children = deleteThisElement.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { org.w3c.dom.Node deleteThisElementChild = children.item(i); if (deleteThisElementChild.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) deleteElementParent.insertBefore(deleteThisElementChild.cloneNode(true), deleteThisElement); } } //remove the element deleteElementParent.removeChild(deleteThisElement); } return writeDocumentToString(subSectionW3CDOM); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("some other error on delete subsections xml string" + ex.toString()); ex.printStackTrace(); } throw new MeleteException("delete_module_fail"); } } public String moveAllUpSection(String sectionsSeqXML, String section_id) throws MeleteException { try { org.w3c.dom.Document subSectionW3CDOM = Xml.readDocumentFromString(sectionsSeqXML); org.w3c.dom.Element root = subSectionW3CDOM.getDocumentElement(); org.w3c.dom.Element moveUpThisElement = subSectionW3CDOM.getElementById(section_id); org.w3c.dom.Node moveUpThisElementParent = moveUpThisElement.getParentNode(); org.w3c.dom.Node cloneMoveElement = moveUpThisElement.cloneNode(true); org.w3c.dom.Node FirstChildOfmoveUpThisElementParent = moveUpThisElementParent.getFirstChild(); if (!FirstChildOfmoveUpThisElementParent.equals(moveUpThisElement)) { moveUpThisElementParent.insertBefore(cloneMoveElement, FirstChildOfmoveUpThisElementParent); moveUpThisElementParent.removeChild(moveUpThisElement); } return writeDocumentToString(subSectionW3CDOM); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("some other error on moving up subsections xml string" + ex.toString()); ex.printStackTrace(); } throw new MeleteException("move_up_fail"); } } public String moveUpSection(String sectionsSeqXML, String section_id) throws MeleteException { try { org.w3c.dom.Document subSectionW3CDOM = Xml.readDocumentFromString(sectionsSeqXML); org.w3c.dom.Element root = subSectionW3CDOM.getDocumentElement(); org.w3c.dom.Element moveUpThisElement = subSectionW3CDOM.getElementById(section_id); org.w3c.dom.Node moveUpThisElementParent = moveUpThisElement.getParentNode(); org.w3c.dom.Node cloneMoveElement = moveUpThisElement.cloneNode(true); if (!moveUpThisElementParent.getFirstChild().equals(moveUpThisElement)) { org.w3c.dom.Node beforeElement = moveUpThisElement.getPreviousSibling(); moveUpThisElementParent.insertBefore(cloneMoveElement, beforeElement); moveUpThisElementParent.removeChild(moveUpThisElement); } return writeDocumentToString(subSectionW3CDOM); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("some other error on moving up subsections xml string" + ex.toString()); ex.printStackTrace(); } throw new MeleteException("move_up_fail"); } } public String moveDownSection(String sectionsSeqXML, String section_id) throws MeleteException { try { org.w3c.dom.Document subSectionW3CDOM = Xml.readDocumentFromString(sectionsSeqXML); org.w3c.dom.Element root = subSectionW3CDOM.getDocumentElement(); org.w3c.dom.Element moveDownThisElement = subSectionW3CDOM.getElementById(section_id); org.w3c.dom.Node afterElementParent = moveDownThisElement.getParentNode(); if (!afterElementParent.getLastChild().equals(moveDownThisElement)) { org.w3c.dom.Node afterElement = moveDownThisElement.getNextSibling(); org.w3c.dom.Node cloneafterElement = afterElement.cloneNode(true); afterElementParent.insertBefore(cloneafterElement, moveDownThisElement); afterElementParent.removeChild(afterElement); } return writeDocumentToString(subSectionW3CDOM); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("some other error on moving down subsections xml string" + ex.toString()); ex.printStackTrace(); } throw new MeleteException("move_down_fail"); } } public String moveAllDownSection(String sectionsSeqXML, String section_id) throws MeleteException { try { org.w3c.dom.Document subSectionW3CDOM = Xml.readDocumentFromString(sectionsSeqXML); org.w3c.dom.Element root = subSectionW3CDOM.getDocumentElement(); org.w3c.dom.Element moveDownThisElement = subSectionW3CDOM.getElementById(section_id); org.w3c.dom.Node cloneMoveElement = moveDownThisElement.cloneNode(true); org.w3c.dom.Node afterElementParent = moveDownThisElement.getParentNode(); org.w3c.dom.Node LastChildOfafterElementParent = afterElementParent.getLastChild(); org.w3c.dom.Node cloneLastChildElement = LastChildOfafterElementParent.cloneNode(true); if (!LastChildOfafterElementParent.equals(moveDownThisElement)) { afterElementParent.replaceChild(cloneMoveElement, LastChildOfafterElementParent); org.w3c.dom.Node newLastChild = afterElementParent.getLastChild(); afterElementParent.insertBefore(cloneLastChildElement, newLastChild); afterElementParent.removeChild(moveDownThisElement); } return writeDocumentToString(subSectionW3CDOM); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("some other error on moving down subsections xml string" + ex.toString()); ex.printStackTrace(); } throw new MeleteException("move_down_fail"); } } /* * */ public org.w3c.dom.Element getNextSection(org.w3c.dom.Element currItem) throws Exception { if (currItem == null) { currParent = subSectionW3CDOM.getDocumentElement(); currLastSection = (org.w3c.dom.Element) currParent.getLastChild(); return (org.w3c.dom.Element) currParent.getFirstChild(); } if (currItem.hasChildNodes()) { currParent = currItem; return (org.w3c.dom.Element) currItem.getFirstChild(); } if (currParent == null) currParent = currItem.getParentNode(); if (currItem.equals((org.w3c.dom.Element) currParent.getLastChild())) { while (true) { if (currParent.getNodeType() == Node.DOCUMENT_NODE) return null; if (!currParent.equals(currLastSection) && !currItem.equals(currLastSection)) { currItem = (org.w3c.dom.Element) currParent.getNextSibling(); if (currItem == null) { logger.debug("going a level up to fetch sibling"); currItem = (org.w3c.dom.Element) currParent; currParent = currItem.getParentNode(); continue; } currParent = currItem.getParentNode(); return currItem; } else return null; } } else return (org.w3c.dom.Element) currItem.getNextSibling(); } /* * */ public org.w3c.dom.Document getSubSectionW3CDOM(String sectionsSeqXML) { try { subSectionW3CDOM = Xml.readDocumentFromString(sectionsSeqXML); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error in getting subsections dom " + ex.toString()); ex.printStackTrace(); } } return subSectionW3CDOM; } public Document createSubSection4jDOM() { if (subSection4jDOM == null) createInitialModule(); return subSection4jDOM; } public void traverseDom(String sectionsSeqXML, String dispSeq) { if (sectionsSeqXML != null) { getSubSectionW3CDOM(sectionsSeqXML); if (subSectionW3CDOM != null) { processDom(subSectionW3CDOM.getDocumentElement(), 0, dispSeq, 1); } } } private void processDom(org.w3c.dom.Node node, int level, String dispSeq, int displayNum) { org.w3c.dom.NodeList nl = node.getChildNodes(); StringBuffer dispSeqBuffer; String displaySequence; for (int i = 0, cnt = nl.getLength(); i < cnt; i++) { if (nl.item(i).getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) { dispSeqBuffer = new StringBuffer(); dispSeqBuffer.append(dispSeq); dispSeqBuffer.append("."); dispSeqBuffer.append(displayNum++); displaySequence = dispSeqBuffer.toString(); dispSeqBuffer = null; xmlSecList.add( new SecLevelObj(Integer.parseInt(((org.w3c.dom.Element) nl.item(i)).getAttribute("id")), level, displaySequence)); processDom(nl.item(i), level + 1, displaySequence, 1); } } } public List getXmlSecList() { return xmlSecList; } public List getAllSections(String modSeqXml) throws Exception { List allsections = null; subSection4jDOM = DocumentHelper.parseText(modSeqXml); setInternalDTD(); Element root = subSection4jDOM.getRootElement(); allsections = subSection4jDOM.selectNodes("//section"); return allsections; } public org.w3c.dom.Element getPrevSection(org.w3c.dom.Document ssW3cDom, org.w3c.dom.Element currItem) throws Exception { org.w3c.dom.Element rootElement = ssW3cDom.getDocumentElement(); org.w3c.dom.Element returnElement = null; if (currItem == rootElement.getFirstChild()) { return null; } org.w3c.dom.Node returnParrent = currItem.getParentNode(); returnElement = (org.w3c.dom.Element) currItem.getPreviousSibling(); if (returnElement != null && returnElement.hasChildNodes()) returnElement = (org.w3c.dom.Element) returnElement.getLastChild(); if (returnElement == null) { returnElement = (org.w3c.dom.Element) returnParrent; } return returnElement; } public int noOfTopLevelSections(String modSeqXml) { try { subSection4jDOM = DocumentHelper.parseText(modSeqXml); setInternalDTD(); Element root = subSection4jDOM.getRootElement(); return root.elements().size(); } catch (Exception e) { return 0; } } } class SecLevelObj { int sectionId, level; String dispSeq; public SecLevelObj(int sectionId, int level, String dispSeq) { this.sectionId = sectionId; this.level = level; this.dispSeq = dispSeq; } public int getSectionId() { return sectionId; } public int getLevel() { return level; } public String getDispSeq() { return dispSeq; } }