source: trunk/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/AbstractHierarchyNode.java@ 12188

Last change on this file since 12188 was 12188, checked in by kjdon, 18 years ago

Initial revision

  • Property svn:keywords set to Author Date Id Revision
File size: 11.7 KB
Line 
1package org.greenstone.gsdl3.gs3build.classifier;
2
3import java.util.List;
4import java.util.ArrayList;
5import java.util.Iterator;
6
7import java.sql.ResultSet;
8import java.sql.SQLException;
9import java.sql.Statement;
10
11import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
12
13import org.greenstone.gsdl3.gs3build.database.*;
14
15public abstract class AbstractHierarchyNode
16{
17 String prefix; // a basic prefix used in this hierarchy
18 String descriptor; // the textual descriptor used on screen or long-hand
19 String name; // the index number, letter assignment or other item
20 // used to identify the position of the item in the
21 // hierarchy
22 String id; // an identifier used by the GLI for maintenance
23 // purposes; this plays no active role in the
24 // rebuilding process (at the moment)
25 List childNodes; // the child classification nodes of this node
26 List childDocs; // the child documents of this node
27 List matches; // the other metadata values that may be matched
28 // against the classifier
29 AbstractHierarchyNode parent; // the parent of the node
30
31 class AbstractHierarchyDocument
32 { DocumentID documentId;
33 String sortKey;
34
35 public AbstractHierarchyDocument(DocumentID documentId, String sortKey)
36 { this.documentId = documentId;
37 this.sortKey = sortKey;
38 }
39
40 public DocumentID getID()
41 { return this.documentId;
42 }
43
44 public String toString()
45 { return this.sortKey;
46 }
47 }
48
49 /**
50 * Simple node
51 */
52 public AbstractHierarchyNode()
53 { this.descriptor = "";
54 this.name = "";
55 this.id = "";
56 this.prefix = "";
57 this.childNodes = new ArrayList();
58 this.childDocs = new ArrayList();
59 this.parent = null;
60 this.matches = new ArrayList();
61 }
62
63 public AbstractHierarchyNode(String prefix, String name, String id, String descriptor)
64 { this.descriptor = descriptor;
65 this.name = name;
66 this.id = id;
67 this.prefix = prefix;
68 this.childNodes = new ArrayList();
69 this.childDocs = new ArrayList();
70 this.parent = null;
71 this.matches = new ArrayList();
72 this.matches.add(this.id);
73 this.matches.add(this.name);
74 }
75
76 public void addChild(AbstractHierarchyNode child)
77 { this.childNodes.add(child);
78 child.setParent(this);
79
80 /**
81 if (this.id == null) {
82 System.out.println(child.id.toString() + " added to root");
83 }
84 else {
85 System.out.println(child.id.toString() + " added to " + this.id);
86 }
87 */
88 }
89
90 public boolean add(AbstractHierarchyNode child)
91 { if (this.id != null && this.id.length() > 0 &&
92 !child.id.startsWith(this.id + "."))
93 { return false;
94 }
95
96 Iterator subNodes = this.childNodes.iterator();
97 while (subNodes.hasNext()) {
98 AbstractHierarchyNode subNode = (AbstractHierarchyNode) subNodes.next();
99
100 if (subNode.add(child)) {
101 return true;
102 }
103 }
104
105 this.addChild(child);
106 return true;
107 }
108
109 public void addDocument(DocumentID document, String sortKey)
110 { if (sortKey == null && false) {
111 System.err.println("attempt to classify by an unset key");
112 return;
113 }
114 this.childDocs.add(new AbstractHierarchyDocument(document, sortKey));
115
116 System.out.println("Adding " + document.toString() + " to " + this.name + " " + this.childDocs.size());
117 if (sortKey != null) {
118 int first = 0;
119 int last = this.childDocs.size() - 1;
120
121 while (first != last) {
122 int at = (first + last) / 2;
123
124 System.out.println(this.name + " " + at + " " + this.childDocs.size() + " " + this.childDocs.get(at) + " " + sortKey);
125 if (this.childDocs.get(at) == null ||
126 this.childDocs.get(at).toString() == null) {
127 last = at;
128 System.out.println("COntinuing");
129 continue;
130 }
131
132 if (this.childDocs.get(at).toString().compareTo(sortKey) > 0) {
133 last = at;
134 }
135 else {
136 first = at + 1;
137 }
138 }
139
140 Object newItem = this.childDocs.get(this.childDocs.size() - 1);
141 last = this.childDocs.size() - 1;
142 while (last > first) {
143 this.childDocs.set(last, this.childDocs.get(last-1));
144 last --;
145 }
146 this.childDocs.set(first, newItem);
147 }
148
149 // System.out.println("Added " + document.toString() + " to " + this.name + " " + this.childDocs.size());
150 // for (int a = 0; a < this.childDocs.size(); a ++) {
151 //System.out.println(this.childDocs.get(a));
152 //}
153 }
154
155 public void setParent(AbstractHierarchyNode parent)
156 { this.parent = parent;
157 }
158
159 public AbstractHierarchyNode getParent()
160 { return this.parent;
161 }
162
163 public String getParentId()
164 {
165 if (this.id == null) {
166 return "";
167 }
168
169 int dotAt = this.id.lastIndexOf('.');
170 if (dotAt < 0) {
171 return "";
172 }
173 return this.id.substring(0, dotAt);
174 }
175
176 public void setDescriptor(String descriptor)
177 { this.descriptor = descriptor;
178 }
179
180 public void setID(String id)
181 { this.id = id;
182 this.matches.add(id);
183 }
184
185 public String getID()
186 { return this.id;
187 }
188
189 public int noOfChildDocs()
190 { return this.childDocs.size();
191 }
192
193 public int noOfLeafDocs()
194 { int total = this.childDocs.size();
195
196 Iterator iterator = this.childNodes.iterator();
197 while (iterator.hasNext()) {
198 AbstractHierarchyNode childNode = (AbstractHierarchyNode) iterator.next();
199
200 total += childNode.noOfLeafDocs();
201 }
202
203 return total;
204 }
205
206 /**
207 * Set the name for this hierarchy node - i.e. its brief description
208 *
209 * @param <code>String</code> the new node name.
210 */
211 public void setName(String name)
212 { this.name = name;
213 this.matches.add(name);
214 }
215
216 /**
217 * Get the name for this hierarchy node - i.e. its brief description
218 *
219 * @return <code>String</code> the node's name.
220 */
221 public String getName()
222 { return this.name;
223 }
224
225 /**
226 * Add another string which can be used to describe this hierarchy node - i.e. one which if
227 * found in a document would indicate that that document belongs to this hierarchy node.
228 *
229 * @param <code>String</code> the string to match.
230 */
231 public void addMatch(String match)
232 { this.matches.add(match);
233 }
234
235 /**
236 * Check if a given string matches any of the values given for this hierarchy node...
237 *
238 * @param <code>String</code> the descriptive string to be compared against the hierarchy
239 * @return <code>boolean</code> <code>true</code> whether the string matches this hierarchy
240 */
241 public boolean isMatch (String toMatch)
242 { Iterator thisMatch = this.matches.iterator();
243
244 while (thisMatch.hasNext())
245 { String thisMatchText = thisMatch.next().toString();
246
247 if (thisMatchText.equals(toMatch))
248 { return true;
249 }
250 }
251 return false;
252 }
253
254 /**
255 * Take a document, and find the classifications that it matches against in
256 * the current hierarchy.
257 *
258 * @param <code>DocumentID</code> the id of the document being classified
259 * @param <code>List</code> the values against which the classifier should
260 * test for the document being a match - i.e. the pertinent document
261 * property values.
262 * @param <code>ClassifierObserverInterface</code>
263 * object modifies the document with information about the
264 * classifications that it fell within.
265 */
266 abstract public void getClassifications(DocumentID documentID, List values, String sortKey,
267 ClassifierObserverInterface observer);
268
269 public boolean writeSQL(GS3SQLConnection connection)
270 {
271 int classifyRef;
272 GS3SQLAction action = null;
273 GS3SQLSelect select;
274 GS3SQLInsert insert;
275
276 Statement statement;
277 // can we connect to the database?
278 try {
279 statement = connection.createStatement();
280 } catch (SQLException e) {
281 System.err.println("AbstractHierarchyNode.writeSQL(): "+e);
282 return false;
283 }
284
285 // Get own full id
286 String fullId = this.id.length() > 0 ? this.prefix+"."+this.id : this.prefix;
287
288 // check for an existing instance of this classifier
289 select = new GS3SQLSelect("classifiers");
290 select.addField("ClassifyRef");
291 GS3SQLWhereItem whereItem = new GS3SQLWhereItem("ClassifyID", "=", fullId);
292 GS3SQLWhere where = new GS3SQLWhere(whereItem);
293 select.setWhere(where);
294
295
296 // update or insert the classifier as required
297 try {
298 ResultSet results = statement.executeQuery(select.toString());
299 if (results.first()) {
300 GS3SQLUpdate update = new GS3SQLUpdate("classifiers");
301 update.setWhere(where);
302 action = update;
303
304 classifyRef = results.getInt("ClassifyRef");
305 }
306 else {
307 insert = new GS3SQLInsert("classifiers");
308
309 if (this.id == null || this.id.length() == 0) {
310 insert.addValue("ParentID", "");
311 }
312 else {
313 String parentId = this.getParentId();
314
315 if (parentId.length() > 0) {
316 insert.addValue("ParentID", this.prefix+"."+this.getParentId());
317 }
318 else {
319 insert.addValue("ParentID", this.prefix);
320 }
321 }
322
323 action = insert;
324 classifyRef = -1;
325 }
326 action.addValue("ClassifyID", fullId);
327 action.addValue("Name", this.name);
328 action.addValue("Description", this.descriptor);
329
330 String tailId = "0";
331 if (this.id.length() > 0) {
332 int lastDot = this.id.lastIndexOf('.');
333 if (lastDot >= 0) {
334 tailId = this.id.substring(lastDot+1);
335 }
336 else {
337 tailId = this.id;
338 }
339 }
340 action.addValue("ClassifyOrder", tailId, GS3SQLField.INTEGER_TYPE);
341 action.addValue("NumLeafDocs", Integer.toString(this.noOfLeafDocs()), GS3SQLField.INTEGER_TYPE);
342
343 statement.execute(action.toString());
344 }
345 catch (SQLException sqlEx) {
346 if (action == null) {
347 System.err.println("AbstractHierarchyNode.writeSQL(): "+sqlEx);
348 }
349 else {
350 System.err.println("AbstractHierarchyNode.writeSQL(): "+sqlEx + " " + action.toString());
351 }
352 return false;
353 }
354
355 // get the ClassifyRef if we don't already have it (have done a
356 // insert action above)...
357 if (classifyRef == -1) {
358 try {
359 ResultSet results = statement.executeQuery(select.toString());
360 if (!results.first()) {
361 statement.close();
362 return false;
363 }
364
365 classifyRef = results.getInt("ClassifyRef");
366
367 }
368 catch (SQLException sqlEx) {
369 System.err.println("AbstractHierarchyNode.writeSQL(): "+sqlEx);
370 return false;
371 }
372 }
373 else {
374 // TODO: clear 'dead' child classifications
375
376 // delete child documents
377 GS3SQLDelete delete = new GS3SQLDelete("classdocuments");
378 delete.setWhere(where);
379 try {
380 statement.execute(delete.toString());
381 } catch (SQLException e) {
382 System.err.println("AbstractHierarchyNode.writeSQL(): "+e);
383 return false;
384 }
385 }
386
387 // post the child nodes...
388 Iterator iterator = this.childNodes.iterator();
389 while (iterator.hasNext()) {
390 AbstractHierarchyNode childNode = (AbstractHierarchyNode) iterator.next();
391
392 if (!childNode.writeSQL(connection)) {
393 System.out.println("Failed to write " );
394 return false;
395 }
396 }
397
398 // note the child documents...
399 iterator = this.childDocs.iterator();
400 int order = 1;
401 while (iterator.hasNext()) {
402 AbstractHierarchyDocument hierarchyDoc = (AbstractHierarchyDocument) iterator.next();
403 DocumentID docId = hierarchyDoc.getID();
404
405 insert = new GS3SQLInsert("classdocuments");
406 insert.addValue("ClassifyRef", Integer.toString(classifyRef), GS3SQLField.INTEGER_TYPE);
407 insert.addValue("DocID", docId.toString());
408 insert.addValue("DocOrder", Integer.toString(order), GS3SQLField.INTEGER_TYPE);
409 try {
410 statement.execute(insert.toString());
411 } catch (SQLException e) {
412 System.err.println("AbstractHierarchyNode.writeSQL(): "+e);
413 return false;
414 }
415 order ++;
416 }
417 // close the statment
418 try {
419 statement.close();
420 } catch (SQLException e) {
421 System.err.println("AbstractHierarchyNode.writeSQL(): "+e);
422 }
423
424 return true;
425 }
426}
427
428
Note: See TracBrowser for help on using the repository browser.