View Javadoc

1   package net.obsearch.example.ted;
2   
3   
4   import java.util.Iterator;
5   import java.util.LinkedList;
6   import java.util.List;
7   
8   import antlr.Token;
9   import antlr.collections.AST;
10  
11  /**
12   * This class only keeps an artificial root node above all the children to simulate a forest!
13   * This is to match the ideas of the papers
14   * @author amuller
15   *
16   */
17  public class SliceForestStd implements SliceForest  {
18  	private LinkedList<SliceASTForStandardTed> trees;
19  	
20  	private int n = -1;
21  	private int heavyIndex = -1;
22  	
23  	private int getHeavyIndex(){
24  		if(heavyIndex == -1) { updateCachedData();}
25  		return heavyIndex;
26  	}
27  	
28  	public boolean isLeftHeavy(){
29  		
30  		return getHeavyIndex() == 0;
31  	}
32  	
33  	public int getSize(){
34  		if(n == -1){ updateCachedData();}
35  		return n;
36  	}
37  	
38  	public boolean isTree(){
39  		return trees.size() == 1;
40  	}
41  	
42  	public  void updateDescendant(){
43  		assert this.isTree();
44  		this.trees.getLast().updateDecendantInformation();
45  	}
46  	
47  	
48  	public void updateIdInfo(){
49  		assert this.isTree();
50  		this.trees.getLast().updateIdInfo();
51  	}
52  	
53  	public void updateContains(){
54  		assert this.isTree();
55  		this.updateIdInfo();
56  		this.trees.getLast().updateContains();
57  	}
58  	
59  	protected void updateCachedData(){
60  		Iterator<SliceASTForStandardTed> it = trees.iterator();
61  		int i =0;
62  		n = 0;
63  		int heavy_value = -1;
64  		while(it.hasNext()){
65  			SliceASTForStandardTed node = it.next();
66  			if(node.getDescendants() > heavy_value ){
67  				heavyIndex = i;
68  				heavy_value = node.getDescendants();
69  			}
70  			i++;
71  			this.n += node.getSize();
72  		}
73  	}
74  	
75  	public SliceForestStd(){
76  		this.treeSet( new LinkedList<SliceASTForStandardTed>());
77  	}
78  	
79  	public SliceForestStd(SliceASTForStandardTed t){
80  		trees = new LinkedList<SliceASTForStandardTed>();
81  		this.treeAddRight(t);
82  	}
83  	
84  	private SliceForestStd(LinkedList<SliceASTForStandardTed> t){
85  		this.treeSet(t);
86  	}
87  	
88  	private void emptyCache(){
89  		this.heavyIndex = -1;
90  		this.n = -1;
91  	}
92  	
93  	private void treeSet(LinkedList<SliceASTForStandardTed> t){
94  		trees = t;
95  		emptyCache();
96  	}
97  	private void treeAddRight(SliceASTForStandardTed t){
98  		trees.add(t);
99  		emptyCache();
100 	}
101 	
102 	private void treeAddLeft(SliceASTForStandardTed t){
103 		trees.addFirst(t);
104 		emptyCache();
105 	}
106 	
107 	private void treeRemoveRight(){
108 		trees.removeLast();
109 		emptyCache();
110 	}
111 	
112 	private void treeRemoveLeft(){
113 		trees.removeFirst();
114 		emptyCache();
115 	}
116 	
117 	
118 	/** Just creates a new array without copying the trees */
119 	public final SliceForestStd shallowCloneForest(){
120 		LinkedList<SliceASTForStandardTed> n = new LinkedList<SliceASTForStandardTed>();
121 		Iterator<SliceASTForStandardTed> it = trees.iterator();
122 		while(it.hasNext()){
123 			n.add(it.next());
124 		}
125 		return new SliceForestStd(n);
126 	}
127 	
128 	/**
129 	 * Adds at the end of the forest (right) the given SliceAST and all his sibblings
130 	 */
131 	protected final void appendSiblings(SliceASTForStandardTed x){
132 		SliceASTForStandardTed p = x;
133 		while(p != null){
134 			this.treeAddRight(p);
135 			p = (SliceASTForStandardTed) p.getNextSibling();
136 		}		
137 	}
138 	
139 	protected final void insertSiblings(SliceASTForStandardTed x){
140 		SliceASTForStandardTed p = x;
141 		if(x != null){
142 			insertSiblings((SliceASTForStandardTed)x.getNextSibling());
143 			this.treeAddLeft(x);
144 		}
145 	}
146 	
147 	/* (non-Javadoc)
148 	 * @see furia.slice.SliceForest#deleteRightTreeNode()
149 	 */
150 	public final SliceForestStd deleteRightTreeNode(){
151 		//assert ! isNull();
152 		LinkedList<SliceASTForStandardTed> n = new LinkedList<SliceASTForStandardTed>();
153 		int s = trees.size() - 1;
154 		Iterator<SliceASTForStandardTed> it = trees.iterator();
155 		int i = 0 ;
156 		while(true){
157 			SliceASTForStandardTed j = it.next();
158 			if(i < s){
159 			n.add(j);
160 			}else{
161 				break;
162 			}
163 			i++;
164 		}
165 		SliceForestStd res = new SliceForestStd(n);
166 		res.appendSiblings( this.getRightTree().getLeftmostChild());
167 		return res;
168 	}
169 	
170 	public final SliceForestStd deleteLeftTreeNode(){
171 		//assert ! isNull();
172 		LinkedList<SliceASTForStandardTed> n = new LinkedList<SliceASTForStandardTed>();
173 		Iterator<SliceASTForStandardTed> it = trees.iterator();
174 		int i = 0 ;
175 		while(it.hasNext()){
176 			SliceASTForStandardTed j = it.next();
177 			if(i != 0){
178 			n.add(j);
179 			}
180 			i++;
181 		}
182 		SliceForestStd res = new SliceForestStd(n);
183 		res.insertSiblings( this.getLeftTree().getLeftmostChild());
184 		return res;
185 	}
186 		
187 	protected final void deleteRightTreeNodeDestructive(){
188 		//assert ! isNull();
189 		SliceASTForStandardTed sibling = this.getRightTree().getLeftmostChild();
190 		this.treeRemoveRight();
191 		this.appendSiblings( sibling );
192 	}
193 	
194 	protected final void deleteLeftTreeNodeDestructive(){
195 		//assert ! isNull();
196 		SliceASTForStandardTed sibling = this.getLeftTree().getLeftmostChild();
197 		this.treeRemoveLeft();
198 		this.insertSiblings( sibling );
199 	}
200 	
201 	/* (non-Javadoc)
202 	 * @see furia.slice.SliceForest#deleteRightTree()
203 	 */
204 	public final SliceForestStd deleteRightTree(){
205 		//assert ! isNull();
206 		SliceForestStd res = shallowCloneForest();
207 		res.treeRemoveRight();
208 		return res;
209 	}
210 	
211 	public final SliceForestStd deleteLeftTree(){
212 		//assert ! isNull();
213 		SliceForestStd res = shallowCloneForest();
214 		res.treeRemoveLeft();
215 		return res;
216 	}
217 	
218 	/* (non-Javadoc)
219 	 * @see furia.slice.SliceForest#getRightTree()
220 	 */
221 	public final SliceASTForStandardTed getRightTree(){
222 		return trees.getLast();
223 	}
224 	
225 	/* (non-Javadoc)
226 	 * @see furia.slice.SliceForest#getLeftTree()
227 	 */
228 	public final SliceASTForStandardTed getLeftTree(){
229 		return trees.getFirst();
230 	}
231 	
232 	public final boolean isNull(){
233 		return 0 == trees.size();
234 	}
235 	
236 	public void calculateHeavyPath(){
237 		Iterator<SliceASTForStandardTed> it = trees.iterator();
238 		while(it.hasNext()){
239 			SliceASTForStandardTed s = it.next();
240 			s.updateHeavyPathInformation();
241 		}
242 	}
243 	
244 	public  List<SliceForest> topLight(){
245 		LinkedList <SliceForest> res = new LinkedList <SliceForest>();
246 		int heavy = this.getHeavyIndex();
247 		Iterator<SliceASTForStandardTed> it = trees.iterator();
248 		int i =0;
249 		while(it.hasNext()){
250 			SliceASTForStandardTed s = it.next();
251 			if(i != heavy){
252 				res.add(new SliceForestStd(s));
253 			}else{
254 				Iterator<SliceASTForStandardTed> it2 = s.topLight().iterator();
255 				while( it2.hasNext() ){
256 				res.add(new SliceForestStd(it2.next()));
257 				}
258 			}
259 			i++;
260 		}
261 		return res;
262 	}
263 	
264 	/* (non-Javadoc)
265 	 * @see furia.slice.SliceForest#deleteRootOnRightTreeAndGetRightTree()
266 	 */
267 	public final SliceForestStd deleteRootOnRightTreeAndGetRightTree(){
268 		SliceForestStd n = new SliceForestStd(getRightTree());
269 		n.deleteRightTreeNodeDestructive();
270 		return n;
271 	}
272 	
273 	
274 	public final SliceForestStd deleteRootOnLeftTreeAndGetLeftTree(){
275 		SliceForestStd n = new SliceForestStd(getLeftTree());
276 		n.deleteLeftTreeNodeDestructive();
277 		return n;
278 	}
279 	/* the hash code for this forest is just a list of the hash codes of each of the 
280 	 * heads of each member of the trees array. That will give a unique representation
281 	 * of a forest
282 	 * return a string with the hash code that represents this forest
283 	 * @see furia.slice.SliceForest#hashString()
284 	 */
285 	public final String hashString(){
286 		StringBuilder res = new StringBuilder();
287 		Iterator<SliceASTForStandardTed> it = trees.iterator();
288 		while(it.hasNext()){
289 			res.append(it.next().hashCode());
290 			res.append("-");
291 		}
292 		return res.toString();
293 	}
294 	
295 	public String prettyPrint(){
296 		StringBuilder res = new StringBuilder();
297 		Iterator<SliceASTForStandardTed> it = trees.iterator();
298 		while(it.hasNext()){
299 			res.append(it.next().toStringTree());
300 		}
301 		return res.toString();
302 	}
303 	
304 	public boolean equalsTree(SliceForest o){
305 	    SliceForestStd obj = (SliceForestStd) o;
306 	    boolean res = true;
307 	    if(trees.size() != obj.trees.size()){
308 	        return false;
309 	    }
310 	    Iterator<SliceASTForStandardTed> it = trees.iterator();
311 	    Iterator<SliceASTForStandardTed> it2 = obj.trees.iterator();
312 	    while(it.hasNext()){
313 	        SliceASTForStandardTed s = it.next();
314 	        SliceASTForStandardTed s2 = it2.next();
315 	        if(! s.equalsTree(s2)){
316 	            res = false;
317 	            break;
318 	        }
319 	    }
320 	    return res;
321 	}
322 
323 	public final String toFuriaChanTree(){
324 	    if(trees.size() != 1){
325                 throw new UnsupportedOperationException("This is not a tree, it is a forest :(");
326             }
327 	        StringBuilder sb = new StringBuilder();
328 	        trees.get(0).toFuriaChanTreeAux(sb);
329 	        return sb.toString();
330 	    }
331 
332 	    
333 }