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

Last change on this file since 7307 was 7307, checked in by kjdon, 20 years ago

setName now adds the name to the list of matches

  • Property svn:keywords set to Author Date Id Revision
File size: 10.5 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.util.GS3SQLConnection;
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 { this.childDocs.add(new AbstractHierarchyDocument(document, sortKey));
111
112 if (sortKey != null) {
113 int first = 0;
114 int last = this.childDocs.size() - 1;
115
116 while (first != last) {
117 int at = (first + last) / 2;
118
119 if (this.childDocs.get(at) == null) {
120 last = at;
121 continue;
122 }
123
124 if (this.childDocs.get(at).toString().compareTo(sortKey) > 0) {
125 last = at;
126 }
127 else {
128 first = at + 1;
129 }
130 }
131
132 Object newItem = this.childDocs.get(this.childDocs.size() - 1);
133 last = this.childDocs.size() - 1;
134 while (last > first) {
135 this.childDocs.set(last, this.childDocs.get(last-1));
136 last --;
137 }
138 this.childDocs.set(first, newItem);
139 }
140 }
141
142 public void setParent(AbstractHierarchyNode parent)
143 { this.parent = parent;
144 }
145
146 public AbstractHierarchyNode getParent()
147 { return this.parent;
148 }
149
150 public String getParentId()
151 {
152 if (this.id == null) {
153 return "";
154 }
155
156 int dotAt = this.id.lastIndexOf('.');
157 if (dotAt < 0) {
158 return "";
159 }
160 return this.id.substring(0, dotAt);
161 }
162
163 public void setDescriptor(String descriptor)
164 { this.descriptor = descriptor;
165 }
166
167 public void setID(String id)
168 { this.id = id;
169 this.matches.add(id);
170 }
171
172 public String getID()
173 { return this.id;
174 }
175
176 public int noOfChildDocs()
177 { return this.childDocs.size();
178 }
179
180 public int noOfLeafDocs()
181 { int total = this.childDocs.size();
182
183 Iterator iterator = this.childNodes.iterator();
184 while (iterator.hasNext()) {
185 AbstractHierarchyNode childNode = (AbstractHierarchyNode) iterator.next();
186
187 total += childNode.noOfLeafDocs();
188 }
189
190 return total;
191 }
192
193 /**
194 * Set the name for this hierarchy node - i.e. its brief description
195 *
196 * @param <code>String</code> the new node name.
197 */
198 public void setName(String name)
199 { this.name = name;
200 this.matches.add(name);
201 }
202
203 /**
204 * Get the name for this hierarchy node - i.e. its brief description
205 *
206 * @return <code>String</code> the node's name.
207 */
208 public String getName()
209 { return this.name;
210 }
211
212 /**
213 * Add another string which can be used to describe this hierarchy node - i.e. one which if
214 * found in a document would indicate that that document belongs to this hierarchy node.
215 *
216 * @param <code>String</code> the string to match.
217 */
218 public void addMatch(String match)
219 { this.matches.add(match);
220 }
221
222 /**
223 * Check if a given string matches any of the values given for this hierarchy node...
224 *
225 * @param <code>String</code> the descriptive string to be compared against the hierarchy
226 * @return <code>boolean</code> <code>true</code> whether the string matches this hierarchy
227 */
228 public boolean isMatch (String toMatch)
229 { Iterator thisMatch = this.matches.iterator();
230
231 while (thisMatch.hasNext())
232 { String thisMatchText = thisMatch.next().toString();
233
234 if (thisMatchText.equals(toMatch))
235 { return true;
236 }
237 }
238 return false;
239 }
240
241 /**
242 * Take a document, and find the classifications that it matches against in
243 * the current hierarchy.
244 *
245 * @param <code>DocumentID</code> the id of the document being classified
246 * @param <code>List</code> the values against which the classifier should
247 * test for the document being a match - i.e. the pertinent document
248 * property values.
249 * @param <code>ClassifierObserverInterface</code>
250 * object modifies the document with information about the
251 * classifications that it fell within.
252 */
253 abstract public void getClassifications(DocumentID documentID, List values, String sortKey,
254 ClassifierObserverInterface observer);
255
256 public boolean writeSQL(GS3SQLConnection connection)
257 {
258 int classifyRef;
259 GS3SQLAction action = null;
260 GS3SQLSelect select;
261 GS3SQLInsert insert;
262
263 // Get own full id
264 String fullId = this.id.length() > 0 ? this.prefix+"."+this.id : this.prefix;
265
266 // check for an existing instance of this classifier
267 select = new GS3SQLSelect("classifiers");
268 select.addField("ClassifyRef");
269 GS3SQLWhereItem whereItem = new GS3SQLWhereItem("ClassifyID", "=", fullId);
270 GS3SQLWhere where = new GS3SQLWhere(whereItem);
271 select.setWhere(where);
272
273 connection.execute(select.toString());
274
275 // update or insert the classifier as required
276 try {
277 ResultSet results = connection.getResultSet();
278 if (results != null && results.first()) {
279 GS3SQLUpdate update = new GS3SQLUpdate("classifiers");
280 update.setWhere(where);
281 action = update;
282
283 classifyRef = results.getInt("ClassifyRef");
284 }
285 else {
286 insert = new GS3SQLInsert("classifiers");
287
288 if (this.id == null || this.id.length() == 0) {
289 insert.addValue("ParentID", "");
290 }
291 else {
292 String parentId = this.getParentId();
293
294 if (parentId.length() > 0) {
295 insert.addValue("ParentID", this.prefix+"."+this.getParentId());
296 }
297 else {
298 insert.addValue("ParentID", this.prefix);
299 }
300 }
301
302 action = insert;
303 }
304 action.addValue("ClassifyID", fullId);
305 action.addValue("Name", this.name);
306 action.addValue("Description", this.descriptor);
307
308 String tailId = "0";
309 if (this.id.length() > 0) {
310 int lastDot = this.id.lastIndexOf('.');
311 if (lastDot >= 0) {
312 tailId = this.id.substring(lastDot+1);
313 }
314 else {
315 tailId = this.id;
316 }
317 }
318 action.addValue("ClassifyOrder", tailId, GS3SQLField.INTEGER_TYPE);
319 action.addValue("NumLeafDocs", Integer.toString(this.noOfLeafDocs()), GS3SQLField.INTEGER_TYPE);
320
321 connection.execute(action.toString());
322 classifyRef = -1;
323 }
324 catch (SQLException sqlEx) {
325 if (action == null) {
326 System.err.println(sqlEx);
327 }
328 else {
329 System.err.println(sqlEx + " " + action.toString());
330 }
331 return false;
332 }
333
334 // get the ClassifyRef if we don't already have it (have done a
335 // insert action above)...
336 if (classifyRef == -1) {
337 connection.execute(select.toString());
338
339 try {
340 ResultSet results = connection.getResultSet();
341 if (results == null || !results.first()) {
342 return false;
343 }
344
345 classifyRef = results.getInt("ClassifyRef");
346 }
347 catch (SQLException sqlEx) {
348 System.err.println(sqlEx);
349 return false;
350 }
351 }
352 else {
353 // TODO: clear 'dead' child classifications
354
355 // delete child documents
356 GS3SQLDelete delete = new GS3SQLDelete("classdocuments");
357 delete.setWhere(where);
358
359 connection.execute(delete.toString());
360 }
361
362 // post the child nodes...
363 Iterator iterator = this.childNodes.iterator();
364 while (iterator.hasNext()) {
365 AbstractHierarchyNode childNode = (AbstractHierarchyNode) iterator.next();
366
367 if (!childNode.writeSQL(connection)) {
368 System.out.println("Failed to write " );
369 return false;
370 }
371 }
372
373 // note the child documents...
374 iterator = this.childDocs.iterator();
375 int order = 1;
376 while (iterator.hasNext()) {
377 AbstractHierarchyDocument hierarchyDoc = (AbstractHierarchyDocument) iterator.next();
378 DocumentID docId = hierarchyDoc.getID();
379
380 insert = new GS3SQLInsert("classdocuments");
381 insert.addValue("ClassifyRef", Integer.toString(classifyRef), GS3SQLField.INTEGER_TYPE);
382 insert.addValue("DocID", docId.toString());
383 insert.addValue("DocOrder", Integer.toString(order), GS3SQLField.INTEGER_TYPE);
384
385 connection.execute(insert.toString());
386
387 order ++;
388 }
389 return true;
390 }
391}
392
393
Note: See TracBrowser for help on using the repository browser.