/*************************************************************************
*
* $RCSfile: OOoNodeHandlingXT.java,v $
*
* $Revision: 1.1.4.1 $
*
* last change: $Author: vg $ $Date: 2005/06/10 13:31:24 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2002 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (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.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2002 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
/**
* Description: This class is used for the transformation of Global documents.
* For each child document referenced by a URL of the text:section a transformation will
* be started.
* This is necessary as global document children don't 'know' of each other nor of the global
* document.
* Due to that no consequence numbering of the chapter would be possible nor a HTML linking between
* child documents an to the content-table (global document).
* The class collects all necessary parameters and starts the transformation of each child document.
*
* This class works only with the XT processor of James Clark. This was the easiest way to go and should be
* expanded/splitt later.
* <p>
* For further documentation and updates visit http://xml.openoffice.org/sx2ml
*/
package org.openoffice.xslt;
import java.io.*;
import java.util.*;
import java.net.*;
import java.lang.reflect.Array;
import org.xml.sax.*;
import javax.xml.parsers.SAXParser;
import com.jclark.xsl.sax.*;
import com.jclark.xsl.om.NodeIterator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.EntityResolver;
import org.xml.sax.helpers.XMLReaderFactory;
import org.xml.sax.helpers.XMLReaderAdapter;
import com.jclark.xsl.expr.*;
import com.jclark.xsl.om.*;
import java.lang.NullPointerException;
import javax.xml.parsers.SAXParserFactory;
public class OOoNodeHandlingXT
{
static boolean mDebug = false;
static final byte ELEMENT = 0;
static final byte TEXT = 1;
static final byte ATTRIBUTE = 2;
static final byte ROOT = 3;
static final byte PROCESSING_INSTRUCTION = 4;
static final byte COMMENT = 5;
static final int N_TYPES = 6;
static final byte ALLTYPES = 6; // useful for the "node()" node type test
static NodeIterator contentTableHeadings;
/** To be called from the stylesheet (e.g. common.xsl) */
public static String transformChildren( NodeIterator iter,
String jarRootURL,
String sourceDirURL,
String optionalURLSuffix,
String dpi,
String outputType,
boolean masterDocument,
boolean debug){
try{
if(!OOoTransform.isInitialized){
if(debug)System.err.println("transformChildren() - Initializing XSLT helper!");
OOoTransform.initializeXSLT();
}else
if(debug)System.err.println("transformChildren() - XSLT helper already initialized!");
OOoTransformProps.jarRootURL = jarRootURL;
OOoTransformProps.setAbsoluteSourceDirURL(sourceDirURL);
OOoTransformProps.optionalURLSuffix = optionalURLSuffix;
OOoTransformProps.dpi = dpi;
OOoTransformProps.mOutputType = outputType;
// temporary solution till loggin is established
OOoTransformProps.mDebug = debug;
OOoTransform.mDebug = debug;
mDebug = debug;
OOoTransformProps.mMasterDocument = masterDocument;
OOoTransformProps.mMasterDocumentEnabled = true;
Node root = null;
root = iter.next();
if(root == null) {
System.err.println("root is null!");
System.err.println("sourceDirURL:" + sourceDirURL);
System.err.println("jarRootURL:" + jarRootURL);
System.err.println("iter:" + iter.toString());
}
NodeIterator descIter = new DescendantsOrSelfNodeIterator(root);
CloneableNodeIterator cloneIter= new CloneableNodeIteratorImpl(descIter);
contentTableHeadings = (NodeIterator) cloneIter.clone();
//giving out all nodes of the node-set(NodeIterator) upto a certain element
if(mDebug) printAllNodes((NodeIterator)cloneIter.clone(), OOoMasterDocument.STOP_ELEMENT);
collectData(cloneIter, OOoMasterDocument.STOP_ELEMENT);
for (Enumeration e = OOoMasterDocument.externalDocumentVector.elements(); e.hasMoreElements();) {
String newSourceRef = (String) e.nextElement();
if(!newSourceRef.equals(".")){
OOoMasterDocument.currentChildContentRef = newSourceRef;
if(mDebug) System.out.println("Next child document to be tranformed -> " + newSourceRef);
OOoTransformProps.setDestinationDirURL(null);
OOoTransform.transform(newSourceRef);
}
}
return "Finished transformation of children documents, started from the global document transformation ";
}catch(Exception e){
if(mDebug) System.out.println(e.getMessage());
e.printStackTrace();
}
return null;
}
/**
This function has two purposes.
1) Adding all URLs of linked files of the global document into a vector (OOoMasterDocument.externalDocumentVector variable)
2) To enable the consecutive numbering of chapters along the linked documents, the preceding open headers of a each level
have to be counted and used as a chapter start value.
* @param iter Traverses all nodes of the given iterator upto a certain element (stop_element)
*
* @param stopElement Name of the element, where the traversing of the tree stops.
*
*/
private static void collectData(NodeIterator iter, String stopElement){
try{
Node node = null;
Name name = null;
Node aNode = null;
Name aName = null;
NodeIterator aIter = null;
String localPart = null;
byte nodeType = 0;
int level = 0;
int childDocumentNo = 0;
int oldChildDocumentNo = 0;
String currentDocumentURL = null;
//for easy usage, we use field and level equalent and ignore the fist field
OOoMasterDocument.initialHeaderLevel = new int[OOoMasterDocument.LEVELMAX + 1];
OOoMasterDocument.externalDocumentVector = new Vector();
OOoMasterDocument.precedingHeaderCounterMap = new HashMap();
if(mDebug) System.out.println("Iterating the node-set from the stylesheet:");
while((node = iter.next()) != null){
nodeType = node.getType();
if(nodeType == ELEMENT){
localPart = node.getName().getLocalPart();
if(localPart.equals("heading")){
level = new Integer(getAttributeValueFrom(node, "level")).intValue();
if(level > OOoMasterDocument.LEVELMAX)
throw new Exception("HeaderLevel exceeds the possible maximum level of headers: "+ OOoMasterDocument.LEVELMAX);
// the incremention of a header results in the restart of all higher levels with zero
for(int i=level+1; i <= OOoMasterDocument.LEVELMAX; i++)
OOoMasterDocument.initialHeaderLevel[i] = 0;
childDocumentNo = new Integer(getAttributeValueFrom(node, "child-document-no")).intValue();
if(childDocumentNo > oldChildDocumentNo){
oldChildDocumentNo = childDocumentNo;
currentDocumentURL = getAttributeValueFrom(node, "file-url");
if(!currentDocumentURL.endsWith("htm") && !currentDocumentURL.endsWith("html")){
OOoMasterDocument.externalDocumentVector.add(currentDocumentURL);
if(mDebug) System.out.println("\nNew global document child:"+currentDocumentURL);
}else
if(mDebug) System.out.println("\nUnvalid global document child :"+currentDocumentURL);
// after the first header in the new document the initial values are determined
// (e.g. when the new document starts with a chapter level 3,
// the preceding chapters of level 1,2 and 3 are used)
OOoMasterDocument.precedingHeaderCounterMap.put(currentDocumentURL, cloneArray(OOoMasterDocument.initialHeaderLevel));
}
// the header incremention is updated after the cloning of the initialHeaderLevel,
// otherwise it would be counted double, as the first header is no preceding header
OOoMasterDocument.initialHeaderLevel[level]++;
if (mDebug){
for(int i=1; i<=OOoMasterDocument.LEVELMAX; i++){
System.out.print("L:"+i+"V:"+Integer.toString(OOoMasterDocument.initialHeaderLevel[i])+" ");
}
System.out.println("");
}
} else if(localPart.equals(stopElement)){
if(mDebug) System.out.println("**** Reached the output stop element: " + stopElement);
break;
}
}
}
}catch(Exception e){
if(mDebug) System.out.println(e.getMessage());
e.printStackTrace();
}
}
private static int[] cloneArray(int[] source){
int[] clone = new int[source.length];
for(int i=0; i<source.length; i++)
clone[i] = source[i];
return clone;
}
private static String getAttributeValueFrom(Node ElementNode, String aName){
try{
NodeIterator aIter = ElementNode.getAttributes();
Node aNode = null;
do{
aNode = aIter.next();
}while(!(aNode.getName().getLocalPart().equals(aName)));
return aNode.getData();
}catch(Exception e){
System.out.println(e.getMessage());
e.printStackTrace();
}
return null;
}
/**
* Debugging method:
* Print outs all following node, dependent of the type of the iterator, until a certain named element (stopElement) is reached
*
* @param iter Traverses all nodes of the given iterator upto a certain element (stopElement)
* and prints the content of the nodes to System.out
* @param stopElement Name of the element, where the traversing of the tree stops.
* The element of the provided name is not included.
*
*/
private static void printAllNodes(NodeIterator iter, String stopElement){
try{
Node node = null;
Name name = null;
byte nodeType = 0;
String localPart = null;
while((node = iter.next()) != null){
nodeType = node.getType();
if(nodeType == ELEMENT){
localPart = node.getName().getLocalPart();
if(localPart.equals(stopElement)){
if(mDebug) System.out.println("**** Reached the output stop element: " + stopElement);
break;
}
System.out.print("ELEMENT: ");
System.out.print(localPart);
printValueOfAttributes(node);
}else if(nodeType == TEXT){
System.out.print("TEXT: ");
System.out.println(node.getData());
}else if(nodeType == ATTRIBUTE){
System.out.print("ATTRIBUTE: ");
System.out.println(node.getName().getLocalPart());
}else if(nodeType == ROOT){
System.out.println("ROOT");
}else if(nodeType == PROCESSING_INSTRUCTION){
System.out.print("PROCESSING_INSTRUCTION: ");
System.out.println(node.getData());
}else if(nodeType == COMMENT){
System.out.print("COMMENT: ");
System.out.println(node.getData());
}
}
}catch(Exception e){
if(mDebug) System.out.println(e.getMessage());
e.printStackTrace();
}
}
// this method receives the actual heading level and returns the actual absolute heading level
// if the level is set to 0 the array will be resetted
public static String calcChapterNumbers(double d_Level){
int level = (int) d_Level;
if(OOoMasterDocument.childHeaderLevel == null)
OOoMasterDocument.childHeaderLevel = new int[OOoMasterDocument.LEVELMAX + 1];
// if the level is set to 0 the array will be resetted
if(level == 0){
for(int i=0; i <= OOoMasterDocument.LEVELMAX; i++)
OOoMasterDocument.childHeaderLevel[i] = 0;
return "A new file is being used!";
}else if(level > OOoMasterDocument.LEVELMAX){
System.out.println("HeaderLevel exceeds the possible maximum level of headers: "+ OOoMasterDocument.LEVELMAX);
return "HeaderLevel exceeds the possible maximum level of headers: "+ OOoMasterDocument.LEVELMAX;
}else{
// the incremention of a header results in the restart of all higher levels with zero
for(int i=level+1; i <= OOoMasterDocument.LEVELMAX; i++)
OOoMasterDocument.childHeaderLevel[i] = 0;
OOoMasterDocument.childHeaderLevel[level]++;
int j = OOoMasterDocument.LEVELMAX;
// start giving out heading levels from the first numbers not '0'
for(; j >= 1; j--)
if(OOoMasterDocument.childHeaderLevel[j] != 0)
break;
StringBuffer sb = new StringBuffer("1");
// starts with '1' as level 0 is not existing
for(int i=2; i <= j; i++){
sb.append('_');
sb.append(OOoMasterDocument.childHeaderLevel[i]);
}
return sb.toString();
}
}
/**
* Debugging method:
* This method gives out the Attribute of an given element to System.out with a '@' prefix before the name
* and '=' between name and value, a '; ' is the delimiter of the attibutes.
* Example: '@title='Categories'; @level='4';
*
* @param element Parent element of the attributes to be given out
*/
private static void printValueOfAttributes(Node element){
try{
NodeIterator iter = element.getAttributes();
Node an = null;
Name aName = null;
String prefix = null;
System.out.print(" ");
while((an = iter.next()) != null){
aName = an.getName();
System.out.print((((prefix = aName.getPrefix()) != null) ? "@" + prefix : "@") + aName.getLocalPart() + "='" + element.getAttributeValue(aName) + "'; ");
}
System.out.println("");
}catch(Exception e){
if(mDebug) System.out.println(e.getMessage());
e.printStackTrace();
}
}
}