source: trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/classifier/AbstractHierarchyNode.java@ 8742

Last change on this file since 8742 was 8742, checked in by kjdon, 19 years ago

changed the import statements for GS3SQLConnection and GS3SQLConnectionFactory to reflect their move to the database package

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