source: trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/metadata/METSDivision.java@ 8461

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

added in Chi's changes for METS documents. mostly the addition of new/improved parseXML methods

  • Property svn:keywords set to Author Date Id Revision
File size: 19.9 KB
Line 
1package org.greenstone.gsdl3.gs3build.metadata;
2
3import java.io.PrintWriter;
4
5import java.util.Iterator;
6import java.util.List;
7import java.util.ArrayList;
8import java.util.Map;
9import java.util.LinkedHashMap;
10
11import java.sql.SQLException;
12import java.sql.ResultSet;
13
14import org.w3c.dom.Element;
15import org.w3c.dom.NodeList;
16
17import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
18import org.greenstone.gsdl3.gs3build.util.XMLTools;
19import org.greenstone.gsdl3.gs3build.util.GS3SQLConnection;
20import org.greenstone.gsdl3.gs3build.database.*;
21
22public class METSDivision extends AbstractStructure
23{
24 String order; // see the METS documentation for the meaning of the different
25 String orderLabel; // label types.
26 String userLabel;
27 String type; // e.g. section, chapter, physical or logical, etc.
28 List metadataRefs;
29 List adminRefs;
30 List fileRefs;
31
32 public static final String DIVISION_TYPE = "Division";
33 public static final String DIVISION_TAG = "div";
34 public static final String FPTR_TAG = "fptr";
35
36 public METSDivision(String ID, String order, String orderLabel, String userLabel, String type)
37 { super(ID);
38
39 this.order = order;
40 this.orderLabel = orderLabel;
41 this.userLabel = userLabel;
42 this.type = type;
43 this.fileRefs = new ArrayList();
44 this.metadataRefs = new ArrayList();
45 }
46
47 public String getStructureType()
48 { return DIVISION_TYPE;
49 }
50
51 public String getLabel()
52 { return this.orderLabel;
53 }
54
55 /**
56 * Find all the divisions that match a given list of file group
57 * identifiers...
58 *
59 * @param <code>List</code> the list of identifiers to find
60 * @param <code>List</code> the list into which to place any
61 * matching divisions.
62 */
63 public void findDivisionsForFiles(List listOfFileIdentifiers, List resultList)
64 { Iterator iterator = this.fileRefs.iterator();
65
66 // get the references on this division, and mark if necessary
67 while (iterator.hasNext())
68 { String reference = iterator.next().toString();
69
70 Iterator fileIterator = listOfFileIdentifiers.iterator();
71 while (fileIterator.hasNext())
72 { String fileRef = fileIterator.next().toString();
73
74 if (fileRef.equals(reference))
75 { resultList.add(this);
76 }
77 }
78 }
79
80 // get the child groups, and check each in turn...
81 Iterator groups = this.children.values().iterator();
82 while (groups.hasNext())
83 { METSDivision group = (METSDivision) groups.next();
84
85 group.findDivisionsForFiles(listOfFileIdentifiers, resultList);
86 }
87 }
88
89 /**
90 * Get the namespace from the given set of descriptive blocks...
91 */
92 public METSNamespace findNamespace(String namespaceName, boolean isOpenNamespace,
93 METSDescriptiveSet descriptiveSet)
94 { METSNamespace namespace = null;
95
96 // Special case - no existing metadata references
97 if (this.metadataRefs.size() == 0) {
98 // Create new Descriptive and add it to the descriptive set
99 METSDescriptive descriptive = new METSDescriptive("DM"+this.ID, this.orderLabel);
100 descriptiveSet.addDescriptive(descriptive);
101
102 // Create the namespace and add it to the Descriptive
103 namespace = NamespaceFactory.initNamespace(namespaceName);
104 if (namespace != null)
105 { descriptive.addNamespace(namespace);
106 }
107
108 return namespace;
109 }
110
111 Iterator descriptiveIterator = this.metadataRefs.iterator();
112
113 while (descriptiveIterator.hasNext())
114 { String descriptiveRef = descriptiveIterator.next().toString();
115
116 METSDescriptive descriptive = descriptiveSet.getDescriptiveById(descriptiveRef);
117
118 if (isOpenNamespace) {
119 namespace = descriptive.getOpenNamespace(namespaceName);
120 }
121 else {
122 namespace = descriptive.getNamespace(namespaceName);
123 }
124
125 if (namespace != null)
126 break;
127 }
128
129 // Special case - no such namespace in any descriptive list...
130 if (namespace == null)
131 { // take the first descriptive area...
132 METSDescriptive descriptive = descriptiveSet.getDescriptiveById(this.metadataRefs.get(0).toString());
133
134 // create the namespace, and add it to the METSDescriptive
135 namespace = NamespaceFactory.initNamespace(namespaceName);
136 if (namespace != null)
137 { descriptive.addNamespace(namespace);
138 }
139 }
140
141 return namespace;
142 }
143
144 /**
145 * Add a new file reference to the structure
146 *
147 * @param <code>METSFileID</code> the file to be referenced.
148 */
149 public void addFileReference(METSFileID fileRef)
150 { this.addFileReference(fileRef.toString());
151 }
152
153 public void addFileReference(String fileRef)
154 { this.fileRefs.add(fileRef);
155 }
156
157 /**
158 * Add a new metadata reference to the structure
159 */
160 public void addMetadataReference(String metadataRef)
161 { // TODO: correct the type
162 this.metadataRefs.add(metadataRef);
163 }
164
165 /**
166 * Get all the metadata references
167 *
168 * @return <code>List</code> containing all the references
169 */
170 public List getMetadataReferences()
171 { return this.metadataRefs;
172 }
173
174 /**
175 * Get all the default (first) metadata reference...
176 *
177 * @return <code>List</code> containing all the references
178 */
179 //TODO: check for this first *open* metadata item...
180 public String getDefaultMetadataReference()
181 { if (this.metadataRefs.size() == 0) {
182 return null;
183 }
184 return this.metadataRefs.get(0).toString();
185 }
186
187 /**
188 * Get all the default (first) first filegroup reference...
189 *
190 * @return <code>List</code> containing all the references
191 */
192 public String getDefaultFileReference()
193 { if (this.fileRefs.size() == 0) {
194 return null;
195 }
196 return this.fileRefs.get(0).toString();
197 }
198
199 /**
200 * Get a child or descendant division
201 *
202 * @param <code>String</code> the path to the child division
203 * @return <code>METSDivision</code> the division found.
204 */
205 public METSDivision getDivision(String divisionLabel)
206 { // if the division ID equals this, then process it
207 if (divisionLabel.equals(this.orderLabel)) {
208 return this;
209 }
210
211 // if we just shouldn't be here, then error...
212 if (!divisionLabel.startsWith(this.orderLabel + ".")) {
213 return null;
214 }
215
216 // get the next division in the division path...
217 String subdivisionPath = divisionLabel.substring(this.orderLabel.length() + 1);
218 String nextDivision = getTopDivisionName(subdivisionPath);
219 String nextLabel;
220
221 // first try the current division name with an appended '.' and the next child id...
222 METSDivision child = (METSDivision) this.children.get(this.orderLabel + "." + nextDivision);
223 if (child == null)
224 { // if that didn't work, try the next division on its own
225 child = (METSDivision) this.children.get(nextDivision);
226
227 // if neither worked, then abort...
228 if (child == null) {
229 return null;
230 }
231 else {
232 // set the next identifier
233 nextLabel = METSDivision.getSubDivisionName(divisionLabel);
234 }
235 }
236 else {
237 // set the next identifier...
238 nextLabel = divisionLabel;
239 }
240
241 return child.getDivision(nextLabel);
242 }
243
244 /**
245 * A convenience method for splitting a division name - this gives the name
246 * without the leading division label... To be used when division identifiers
247 * are given as '.' separated paths and division names do not contain the
248 * full path of their parents.
249 *
250 * @return <code>String</code>
251 */
252 public static String getSubDivisionName(String divisionName)
253 { int at = divisionName.indexOf('.');
254
255 if (at >= 0)
256 { return divisionName.substring(at+1);
257 }
258 else
259 { return null;
260 }
261 }
262
263 /**
264 * Get the parent division name. Division identifiers
265 * concatenate the ancestor's names with intervening
266 * '.' characters.
267 *
268 * @return <code>String</code> the division name
269 */
270 public static String getParentName(String divisionName)
271 { int at = divisionName.lastIndexOf('.');
272
273 if (at >= 0) {
274 return divisionName.substring(0, at);
275 }
276 return "";
277 }
278
279 /**
280 * Get the top division name.
281 *
282 * @return <code>String</code> the division name
283 */
284 public static String getTopDivisionName(String divisionName)
285 { int at = divisionName.indexOf('.');
286
287 if (at >= 0)
288 { return divisionName.substring(0, at);
289 }
290 else
291 { return divisionName;
292 }
293 }
294
295 /* Parse an XML Element as a METSDivision section
296 *
297 * @param <code>Element</code> the XML element which represents
298 * the mets:div itself
299 */
300
301 public static METSDivision parseXML(Element element)
302 {
303 METSDivision thisDivision = null;
304
305 String divId = element.getAttribute("ID");
306 String divType = element.getAttribute("TYPE");
307 String divOrder = element.getAttribute("ORDER");
308 String divOrderLabel = element.getAttribute("ORDERLABEL");
309 String divUserLabel = element.getAttribute("LABEL");
310 String divMetaRef = element.getAttribute("DMDID");
311
312 thisDivision = new METSDivision(divId, divOrder,divOrderLabel, divUserLabel, divType);
313
314 thisDivision.addMetadataReference(divMetaRef);
315
316 NodeList children = element.getChildNodes();
317
318 for (int c = 0; c < children.getLength(); c++){
319 if (children.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE){
320 continue;
321 }
322 Element child = (Element) children.item(c);
323 String childName = child.getNodeName();
324
325 if (childName.equals("mets:fptr")) {
326
327 METSDivision.fptr_parseXML(thisDivision, child);
328 } else if (childName.equals("mets:div")) {
329 METSDivision division = METSDivision.parseXML(child);
330 thisDivision.addDivision(division);
331 } else {
332 System.err.println("Error: mets:div expected mets:div or mets:fptr, but got " + childName);
333 }
334 }
335 return thisDivision;
336 }
337
338
339
340 /**
341 * Parse an XML element as a METSFptr Section
342 * @param <code>Element</code> the XML element which represents the mets:fptr itself
343 */
344 private static void fptr_parseXML(METSDivision thisDivision, Element element)
345 {
346 String fileRef = element.getAttribute("FILEID");
347 thisDivision.addFileReference(fileRef);
348 }
349
350 /**
351
352
353 /**
354 * Write the METS file in an XML to a text-output sink.
355 *
356 * @param <code>PrintWriter</code> the destination of the output
357 */
358 public boolean write(PrintWriter writer)
359 { // Get the main tag for the division
360 String tag = XMLTools.getOpenTag("mets", DIVISION_TAG);
361 tag = XMLTools.addAttribute(tag, "ID", this.ID.toString());
362 tag = XMLTools.addAttribute(tag, "TYPE", this.type);
363 tag = XMLTools.addAttribute(tag, "ORDER", this.order);
364 if (this.orderLabel != null)
365 { tag = XMLTools.addAttribute(tag, "ORDERLABEL", this.orderLabel);
366 }
367 if (this.userLabel != null)
368 { tag = XMLTools.addAttribute(tag, "LABEL", this.userLabel);
369 }
370
371 // Add a metadata reference attribute
372 if (this.metadataRefs.size() > 0)
373 { String metaList = this.writeList(this.metadataRefs);
374
375 tag = XMLTools.addAttribute(tag, "DMDID", metaList);
376 }
377
378 // write the central tag
379 writer.println(tag);
380
381 // write the list of file pointers for this structural element
382 if (this.fileRefs.size() > 0)
383 { String fileList = this.writeTagList("mets", "fptr", "FILEID", this.fileRefs);
384
385 writer.println(fileList);
386 }
387
388 // write out any children in turn
389 Iterator groups = this.children.values().iterator();
390
391 while (groups.hasNext())
392 { METSDivision group = (METSDivision) groups.next();
393
394 if (!group.write(writer)) {
395 return false;
396 }
397 }
398
399 // close the div element
400 writer.println(XMLTools.getCloseTag("mets", DIVISION_TAG));
401
402 return true;
403 }
404
405 /**
406 * A convenience method for writing a <code>List</code> as a series of tags...
407 */
408 private String writeTagList(String namespace, String tagname,
409 String attribute, List list)
410 { StringBuffer listString = new StringBuffer();
411
412 Iterator iterator = list.iterator();
413 while (iterator.hasNext())
414 { String item = iterator.next().toString();
415
416 String tag = XMLTools.getOpenTag(namespace, tagname);
417 tag = XMLTools.addAttribute(tag, attribute, item);
418 tag = XMLTools.makeSingleton(tag);
419
420 listString.append(tag);
421 }
422 return listString.toString();
423 }
424
425 /**
426 * A convenience method for writing a <code>List</code> as a space-separated <code>String</code>.
427 */
428 private String writeList(List list)
429 { StringBuffer listString = new StringBuffer();
430
431 Iterator iterator = list.iterator();
432 while (iterator.hasNext())
433 { String item = iterator.next().toString();
434
435 if (listString.length() > 0) {
436 listString.append(" ");
437 }
438
439 listString.append(item);
440 }
441 return listString.toString();
442 }
443
444 public boolean writeSQL(DocumentID docId, int parentRef, boolean parentIsStructure,
445 GS3SQLConnection connection)
446 { int sqlRef = -1;
447
448 // set the "where" to find the reference for this division
449 GS3SQLSelect select = new GS3SQLSelect("divisions");
450 select.addField("DivisionRef");
451 GS3SQLWhereItem whereItem = new GS3SQLWhereItem("ParentRef", "=", Integer.toString(parentRef), GS3SQLField.INTEGER_TYPE);
452 GS3SQLWhereItem parentItem = new GS3SQLWhereItem("ParentType", "=", parentIsStructure ? METSStructure.STRUCTURE_TYPE : METSDivision.DIVISION_TYPE);
453 GS3SQLWhereItem item = new GS3SQLWhereItem("SectionID", "=", this.ID.toString());
454 GS3SQLWhere where = new GS3SQLWhere(whereItem);
455 where.add(parentItem);
456 where.add(item);
457 select.setWhere(where);
458
459 connection.execute(select.toString());
460
461 // Do the actual writing
462 GS3SQLAction action;
463
464 ResultSet resultSet = connection.getResultSet();
465 try {
466 if (resultSet == null ||
467 !resultSet.first())
468 { resultSet = null;
469
470 GS3SQLInsert insert = new GS3SQLInsert("divisions");
471 insert.addValue("DocID", docId.toString());
472 insert.addValue("SectionID", this.ID.toString());
473 insert.addValue("ParentRef", Integer.toString(parentRef));
474 insert.addValue("ParentType", parentIsStructure == true ? METSStructure.STRUCTURE_TYPE : METSDivision.DIVISION_TYPE);
475
476 action = insert;
477 }
478 else {
479 sqlRef = resultSet.getInt("DivisionRef");
480
481 GS3SQLUpdate update = new GS3SQLUpdate("divisions");
482 GS3SQLWhere updateWhere =
483 new GS3SQLWhere(new GS3SQLWhereItem("DivisionRef", "=", Integer.toString(sqlRef),
484 GS3SQLField.INTEGER_TYPE));
485 update.setWhere(updateWhere);
486 action = update;
487 }
488 }
489 catch (SQLException sql) {
490 System.err.println(sql + " " + select.toString());
491 return false;
492 }
493
494 action.addValue("DivisionType", this.type.toString());
495 action.addValue("LabelOrder", this.order);
496 action.addValue("ShortLabel", this.orderLabel);
497 action.addValue("UserLabel", this.userLabel);
498
499 if (!connection.execute(action.toString()))
500 { return false;
501 }
502
503 // if doing a fresh item, get the new structure reference...
504 if (resultSet == null)
505 { // get the new structure reference
506 connection.execute(select.toString());
507
508 // get the sql reference for the division
509 try {
510 // read in the structure reference
511 resultSet = connection.getResultSet();
512 if (resultSet == null) {
513 return false;
514 }
515 resultSet.first();
516 sqlRef = resultSet.getInt("DivisionRef");
517 resultSet.close();
518 resultSet = null;
519 }
520 catch (SQLException sqlex) {
521 System.err.println("Unable to retrieve reference for Division " + sqlex);
522 return false;
523 }
524 }
525 // close the open resultSet, as we don't need it any longer...
526 else {
527 try {
528 resultSet.close();
529 }
530 catch (SQLException sql) {
531 System.err.println(sql + " " + select.toString());
532 }
533 }
534
535 // delete the old file/metadata references
536 GS3SQLWhere referenceWhere =
537 new GS3SQLWhere(new GS3SQLWhereItem("DivisionRef", "=", Integer.toString(sqlRef),
538 GS3SQLField.INTEGER_TYPE));
539
540 GS3SQLDelete delete = new GS3SQLDelete("divisionfilerefs");
541 delete.setWhere(referenceWhere);
542 connection.execute(delete.toString());
543
544 delete = new GS3SQLDelete("divisionmetarefs");
545 delete.setWhere(referenceWhere);
546 connection.execute(delete.toString());
547
548 // write the new file references
549 if (this.fileRefs.size() > 0)
550 { Iterator iterator = this.fileRefs.iterator();
551
552 while (iterator.hasNext())
553 { GS3SQLInsert fileinsert = new GS3SQLInsert("divisionfilerefs");
554 fileinsert.addValue("DocID", docId.toString());
555 fileinsert.addValue("DivisionRef", Integer.toString(sqlRef), GS3SQLField.INTEGER_TYPE);
556 fileinsert.addValue("DivisionType", "Group");
557 fileinsert.addValue("FileID", iterator.next().toString());
558 connection.execute(fileinsert.toString());
559 }
560 }
561
562 // write the metadata references
563 if (this.metadataRefs.size() > 0)
564 { Iterator iterator = this.metadataRefs.iterator();
565
566 while (iterator.hasNext())
567 { GS3SQLInsert metainsert = new GS3SQLInsert("divisionmetarefs");
568 metainsert.addValue("DocID", docId.toString());
569 metainsert.addValue("DivisionRef", Integer.toString(sqlRef), GS3SQLField.INTEGER_TYPE);
570 metainsert.addValue("DivisionType", "Group");
571 metainsert.addValue("MetaID", iterator.next().toString());
572 connection.execute(metainsert.toString());
573 }
574 }
575
576 // write out any children in turn
577 Iterator groups = this.children.values().iterator();
578
579 while (groups.hasNext())
580 { METSDivision group = (METSDivision) groups.next();
581
582 if (!group.writeSQL(docId, sqlRef, false, connection)) {
583 return false;
584 }
585 }
586 return true;
587 }
588
589 public static METSDivision readSQL(GS3SQLConnection connection, ResultSet resultSet)
590 {
591 METSLocation metsLocation = null;
592
593 GS3SQLSelect select = null;
594 try {
595 // read the basic information
596 String ID = resultSet.getString("SectionID");
597 String type = resultSet.getString("DivisionType");
598 String order = resultSet.getString("LabelOrder");
599 String orderLabel = resultSet.getString("ShortLabel");
600 String userLabel = resultSet.getString("UserLabel");
601
602 // construct the division object
603 METSDivision division = new METSDivision(ID, order, orderLabel, userLabel, type);
604
605 // obtain a list of child divisions
606 int divisionRef = resultSet.getInt("DivisionRef");
607
608 select = new GS3SQLSelect("divisions");
609 select.addField("*");
610 GS3SQLWhereItem whereItem = new GS3SQLWhereItem("ParentRef", "=", Integer.toString(divisionRef),
611 GS3SQLField.INTEGER_TYPE);
612 GS3SQLWhere where = new GS3SQLWhere(whereItem);
613 whereItem = new GS3SQLWhereItem("ParentType", "=", METSDivision.DIVISION_TYPE);
614 where.add(whereItem);
615 select.setWhere(where);
616
617 connection.execute(select.toString());
618
619 // circulate through to obtain further children
620 ResultSet childSet = connection.getResultSet();
621 if (childSet.first())
622 {
623 do {
624 METSDivision childDivision = METSDivision.readSQL(connection, childSet);
625 division.addDivision(childDivision);
626 }
627 while (childSet.next());
628 }
629
630 select = new GS3SQLSelect("divisionfilerefs");
631 select.addField("*");
632 where = new GS3SQLWhere(new GS3SQLWhereItem("DivisionRef", "=", Integer.toString(divisionRef),
633 GS3SQLField.INTEGER_TYPE));
634 select.setWhere(where);
635
636 connection.execute(select.toString());
637
638 ResultSet fileSet = connection.getResultSet();
639 if (fileSet != null && fileSet.first())
640 { do
641 { String reference = fileSet.getString("FileID");
642 division.fileRefs.add(reference);
643 }
644 while (fileSet.next());
645 }
646
647 select = new GS3SQLSelect("divisionmetarefs");
648 select.addField("*");
649 where = new GS3SQLWhere(new GS3SQLWhereItem("DivisionRef", "=", Integer.toString(divisionRef),
650 GS3SQLField.INTEGER_TYPE));
651 select.setWhere(where);
652
653 connection.execute(select.toString());
654
655 ResultSet metaSet = connection.getResultSet();
656 if (metaSet != null && metaSet.first())
657 { do
658 { String reference = metaSet.getString("MetaID");
659 division.metadataRefs.add(reference);
660 }
661 while (metaSet.next());
662 }
663
664 return division;
665 }
666 catch (SQLException sqlEx)
667 { System.out.println(sqlEx + " " +select.toString());
668 }
669 return null;
670 }
671}
Note: See TracBrowser for help on using the repository browser.