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