001 /* 002 * Copyright 2009 - 2010 JEuclid, http://jeuclid.sf.net 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 /* $Id $ */ 018 019 package net.sourceforge.jeuclid.biparser; 020 021 import java.util.ArrayList; 022 import java.util.List; 023 024 import net.sourceforge.jeuclid.elements.JEuclidElementFactory; 025 026 import org.xml.sax.Attributes; 027 import org.xml.sax.SAXParseException; 028 029 /** 030 * this class if for creating a BiTree with ABiNodes while parsing a text. 031 * 032 * @version $Revision: 0b66106c7ff7 $ 033 */ 034 public class BiTreeCreationHelper { 035 036 /** current position in tree. */ 037 private IBiNode currentBiNode; 038 /** root of tree. */ 039 private IBiNode root; 040 /** save positions of open tags. */ 041 private final List<Integer> startPositions; 042 043 /** 044 * create a new BiTreeHelper. get result (tree of ABiNodes) with getRoot() 045 */ 046 public BiTreeCreationHelper() { 047 this.startPositions = new ArrayList<Integer>(); 048 } 049 050 /** 051 * get root of BiTree. 052 * 053 * @return root of BiTree 054 */ 055 public final IBiNode getRoot() { 056 return this.root; 057 } 058 059 /** 060 * create and append a new BiNode at current position in BiTree. 061 * 062 * @param totalOffset 063 * of node in text 064 * @param childOffset 065 * position of first child (length of open tag) 066 * @param namespaceURI 067 * namespace 068 * @param eName 069 * name of node 070 * @param attrs 071 * attributes of node 072 * @throws SAXParseException 073 * if the element cannot be recognized by JEuclid. 074 */ 075 public final void createBiNode(final int totalOffset, 076 final int childOffset, final String namespaceURI, 077 final String eName, final Attributes attrs) throws SAXParseException { 078 079 if (JEuclidElementFactory.getJEuclidElementConstructor(namespaceURI, 080 eName) == null) { 081 throw new NonIncrementalElementException(eName); 082 } 083 BiNode biNode; 084 085 this.startPositions.add(totalOffset); 086 087 // new root node 088 if (this.root == null) { 089 this.root = new BiNode(childOffset, namespaceURI, eName, attrs); 090 this.currentBiNode = this.root; 091 } else { 092 biNode = new BiNode(childOffset, namespaceURI, eName, attrs); 093 094 // append child (only possible at start 095 if (this.currentBiNode.getType() == BiType.EMPTY) { 096 this.currentBiNode.addSibling(biNode); 097 } else { 098 // add child (default case) 099 ((BiNode) this.currentBiNode).addChild(biNode); 100 } 101 102 this.currentBiNode = biNode; 103 } 104 } 105 106 /** 107 * close BiNode (set length of node). 108 * 109 * @param length 110 * length of node 111 */ 112 public final void closeBiNode(final int length) { 113 BiNode parent; 114 final int last = this.startPositions.size() - 1; 115 116 this.currentBiNode.setLength(length - this.startPositions.get(last)); 117 118 // move current position to parent 119 parent = this.currentBiNode.getParent(); 120 if (parent != null) { 121 this.currentBiNode = parent; 122 } 123 124 this.startPositions.remove(last); 125 } 126 127 /** 128 * check if current position in BiTree allows a TextNode as child. 129 * 130 * @return true if a TextNode is allowed 131 */ 132 public final boolean allowNewTextNode() { 133 return ((BiNode) this.currentBiNode).getChild() == null; 134 } 135 136 /** 137 * create a new TextNode at current position. 138 * 139 * @param length 140 * length of TextNode 141 * @param t 142 * text of TextNode 143 */ 144 public final void createTextNode(final int length, final String t) { 145 ((BiNode) this.currentBiNode).addChild(new TextNode(length, t)); 146 } 147 148 /** 149 * create a new EmptyNode at current position in BiTree. 150 * 151 * @param length 152 * length of EmtpyNode 153 */ 154 public final void createEmtpyNode(final int length) { 155 // EmptyNode is new root 156 if (this.root == null) { 157 this.root = new EmptyNode(length); 158 this.currentBiNode = this.root; 159 } else { 160 ((BiNode) this.currentBiNode).addChild(new EmptyNode(length)); 161 } 162 } 163 }