View Javadoc

1   package net.obsearch.example;
2   
3   import java.io.DataInputStream;
4   import java.io.DataOutputStream;
5   import java.io.IOException;
6   import java.io.StringReader;
7   import java.util.LinkedList;
8   import java.util.List;
9   import java.util.ListIterator;
10  
11  import net.obsearch.OB;
12  import net.obsearch.exception.OBException;
13  import net.obsearch.ob.OBShort;
14  
15  
16  
17  import antlr.RecognitionException;
18  
19  import com.sleepycat.bind.tuple.TupleInput;
20  import com.sleepycat.bind.tuple.TupleOutput;
21  
22  /*
23   OBSearch: a distributed similarity search engine
24   This project is to similarity search what 'bit-torrent' is to downloads.
25   Copyright (C)  2007 Arnoldo Jose Muller Molina
26  
27   This program is free software; you can redistribute it and/or modify
28   it under the terms of the GNU General Public License as published by
29   the Free Software Foundation; either version 2 of the License, or
30   (at your option) any later version.
31  
32   This program is distributed in the hope that it will be useful,
33   but WITHOUT ANY WARRANTY; without even the implied warranty of
34   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35   GNU General Public License for more details.
36  
37   You should have received a copy of the GNU General Public License along
38   with this program; if not, write to the Free Software Foundation, Inc.,
39   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.   
40   */
41  /**
42   * Example Object that can be stored in OBSearch This class reads strings
43   * representations of trees and calculates the distance between the objects by
44   * using a tree distance function.
45   * @author Arnoldo Jose Muller Molina
46   * @since 0.7
47   */
48  
49  public class OBSlice implements OBShort  {
50  
51      
52  
53      /**
54       * The root node of the tree.
55       */
56      protected SliceAST tree;
57      private int hashCode;
58      
59      
60  
61      /**
62       * Default constructor must be provided by every object that implements the
63       * interface OB.
64       */
65      public OBSlice() {
66  
67      }
68      
69      public SliceAST getTree(){
70      	return tree;
71      }
72  
73      /**
74       * Creates an slice object.
75       * @param slice
76       *                A string representation of a tree.
77       */
78      public OBSlice(final String slice) throws OBException {
79          this.updateTree(slice);
80          assert tree.equalsTree( this.parseTree(tree.toFuriaChanTree())) : "This: " + tree.toFuriaChanTree() + " slice: " + slice + " size: " + tree.getSize();
81      }
82  
83      /**
84       * Calculates the distance between two trees. TODO: traverse the smallest
85       * tree.
86       * @param object
87       *                The other object to compare
88       * @see net.obsearch.OB#distance(net.obsearch.OB,
89       *      net.obsearch.result.Dim)
90       * @throws OBException
91       *                 if something wrong happens.
92       * @return A short that indicates how similar or different the trees are.
93       */
94      public final short distance(final OBShort object) throws OBException {
95          OBSlice b = (OBSlice) object;
96          assert this.tree != null;
97          assert b.tree != null;
98          if (this.tree.getSize() < b.tree.getSize()) {
99              return distance(this.tree, b.tree);
100         } else {
101             return distance(b.tree, this.tree);
102         }
103     }
104 
105     /**
106      * Calculates the distance between trees a and b.
107      * @param a
108      *                The first tree (should be smaller than b)
109      * @param b
110      *                The second tree
111      * @return The distance of the trees.
112      */
113     private final short distance(SliceAST a, SliceAST b) {
114 
115         List < SliceAST > aExpanded = a.depthFirst();
116         List < SliceAST > bExpanded = b.depthFirst();
117         List < SliceAST > bExpanded2 = new LinkedList < SliceAST >();
118         bExpanded2.addAll(bExpanded);
119         int Na = aExpanded.size() * 2;
120         int Nb = bExpanded.size() * 2;
121 
122         ListIterator < SliceAST > ait = aExpanded.listIterator();
123         int res = 0;
124         while (ait.hasNext()) {
125             SliceAST aTree = ait.next();
126             ListIterator < SliceAST > bit = bExpanded.listIterator();
127             while (bit.hasNext()) {
128                 SliceAST bTree = bit.next();
129                 if (aTree.equalsTree(bTree)) {
130                     res++;
131                     bit.remove();
132                     break;
133                 }
134             }
135             // do the same for the nodes without children
136             bit = bExpanded2.listIterator();
137             while (bit.hasNext()) {
138                 SliceAST bTree = bit.next();
139                 if (aTree.getText().equals(bTree.getText())) {
140                     res++;
141                     bit.remove();
142                     break;
143                 }
144             }
145         }
146         // return Na - res + Nb - res;
147         // return (Na + Nb) - ( 2 * res);
148         short r = (short) (((Na + Nb) - (2 * res)) / 2);
149         assert r >= 0;
150         return r;
151     }
152 
153     /**
154      * Internal method that updates the Tree from the String
155      * @throws OBException
156      */
157     protected final void updateTree(String x) throws OBException {
158         tree = parseTree(x);
159         this.hashCode = tree.toFuriaChanTree().hashCode();
160     }
161 
162     private final SliceAST parseTree(String x) throws SliceParseException {
163         try {
164             SliceLexer lexer = new SliceLexer(new StringReader(x));
165             SliceParser parser = new SliceParser(lexer);
166             parser.setASTNodeClass("net.obsearch.example.SliceAST");
167             parser.slice();
168             SliceAST t = (SliceAST) parser.getAST();
169             t.updateDecendantInformation();
170             return t;
171         } catch (Exception e) {
172             throw new SliceParseException(x, e);
173         }
174     }
175     
176     
177 
178     /**
179      * Returns the size (in nodes) of the tree.
180      * @return The size of the tree.
181      * @throws OBException
182      *                 If something goes wrong.
183      */
184     public final int size() throws OBException {
185         return tree.getSize();
186     }
187 
188     /**
189      * @return A String representation of the tree.
190      */
191     public final String toString() {
192         String res = ":)";
193         try {
194             res = tree.toFuriaChanTree() + "|" + tree.getSize() + "|";
195         } catch (Exception e) {
196             assert false;
197         }
198         return res;
199     }
200 
201     /**
202      * Re-creates this object from the given byte stream
203      * @param in
204      *                A byte vector from which the stream will be loaded.
205      * @see net.obsearch.Storable#load(com.sleepycat.bind.tuple.TupleInput)
206      */
207     public final void load(byte [] in) throws IOException, OBException {
208             updateTree(new String(in));
209     }
210     
211     public final int recordSize(){
212     	return 0;
213     }
214 
215     /**
216      * Stores this object into the given byte stream.
217      * @param out
218      *                The byte stream to be used
219      * @see net.obsearch.Storable#store(com.sleepycat.bind.tuple.TupleOutput)
220      */
221     public final byte[] store() throws IOException{
222         return tree.toFuriaChanTree().getBytes();        
223     }
224 
225     /**
226      * Returns true of this.tree.equals(obj.tree). For this distance function
227      * this.distance(obj) == 0 implies that this.equals(obj) == true
228      * @param obj
229      *                Object to compare.
230      * @return true if this == obj
231      */
232     public final boolean equals(final Object obj) {
233         if (!(obj instanceof OBSlice)) {
234             assert false;
235             return false;
236         }
237         OBSlice o = (OBSlice) obj;
238         return tree.equalsTree(o.tree);
239     }
240 
241     /**
242      * A hashCode based on the string representation of the tree.
243      * @return a hash code of the string representation of this tree.
244      */
245     public final int hashCode() {
246         return this.hashCode;
247     }
248 
249 }