source: trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/doctypes/AbstractDocument.java@ 9874

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

merged from branch ant-install-branch: merge 1

  • Property svn:keywords set to Author Date Id Revision
File size: 14.8 KB
Line 
1package org.greenstone.gsdl3.gs3build.doctypes;
2
3import java.util.List;
4import java.util.ArrayList;
5import java.util.Iterator;
6import java.util.HashMap;
7import java.util.Map;
8import java.util.Date;
9
10import java.sql.SQLException;
11import java.sql.Statement;
12import java.sql.ResultSet;
13import java.sql.Timestamp;
14
15import java.net.URL;
16
17import org.greenstone.gsdl3.gs3build.metadata.NamespaceFactory;
18import org.greenstone.gsdl3.gs3build.metadata.StructureIdentifierFactory;
19import org.greenstone.gsdl3.gs3build.metadata.GSDL3Namespace;
20import org.greenstone.gsdl3.gs3build.metadata.METSDescriptiveSet;
21import org.greenstone.gsdl3.gs3build.metadata.METSFile;
22import org.greenstone.gsdl3.gs3build.metadata.METSFileSet;
23import org.greenstone.gsdl3.gs3build.metadata.METSHeader;
24import org.greenstone.gsdl3.gs3build.metadata.METSStructure;
25import org.greenstone.gsdl3.gs3build.metadata.METSStructureSet;
26import org.greenstone.gsdl3.gs3build.metadata.METSDivision;
27import org.greenstone.gsdl3.gs3build.metadata.METSNamespace;
28import org.greenstone.gsdl3.gs3build.metadata.MetadataLabel;
29
30import org.greenstone.gsdl3.gs3build.util.MultiMap;
31import org.greenstone.gsdl3.gs3build.database.GS3SQLConnection;
32
33/**
34 * Provide a base-line functionality for the <code>DocumentInterface</code>
35 * class.
36 */
37
38public abstract class AbstractDocument implements DocumentInterface
39{
40 METSFileSet fileSet;
41 METSDescriptiveSet metadata;
42 METSStructureSet structureSet;
43 METSHeader header;
44 DocumentID id;
45 boolean isModified;
46 StructureIdentifierFactory structureIdFactory;
47 java.sql.Timestamp firstDate;
48 java.sql.Timestamp indexDate;
49 java.sql.Timestamp modifiedDate;
50
51 /**
52 * <p>Create a very vanilla document with a given document identifier.</p>
53 * <p>Most commonly used in dealing with loading files using DocumentFactory
54 * or similar.</p>
55 *
56 * @param <code>DocumentID</code> the document identifier
57 */
58 public AbstractDocument(DocumentID id)
59 { this.fileSet = new METSFileSet();
60 this.metadata = new METSDescriptiveSet();
61 this.header = new METSHeader();
62 this.structureSet = new METSStructureSet();
63 this.id = id;
64 this.structureIdFactory = new StructureIdentifierFactory();
65
66 java.util.Date thisDate = new java.util.Date();
67 this.firstDate = new java.sql.Timestamp(thisDate.getTime());
68 this.indexDate = new java.sql.Timestamp(thisDate.getTime());
69 this.modifiedDate = null; // as a signature that the modified date needs finding...
70 }
71
72 /**
73 * Create a basic document from a given <code>URL</code. This is usually the form
74 * called through the recognisers.
75 *
76 * @param <code>URL</code> the URL of the first file in the document package
77 */
78 public AbstractDocument(URL url)
79 { this.fileSet = new METSFileSet();
80 METSFile metsFile = this.fileSet.addFile(url);
81 this.metadata = new METSDescriptiveSet();
82 this.header = new METSHeader();
83 this.structureSet = new METSStructureSet();
84 this.id = null;
85
86 java.util.Date thisDate = new java.util.Date();
87 this.firstDate = new java.sql.Timestamp(thisDate.getTime());
88 this.indexDate = new java.sql.Timestamp(thisDate.getTime());
89
90 METSStructure structure = new METSStructure("All", "All", "Whole Document");
91 METSDivision documentBody = new METSDivision("All", "All", "All", "Whole Document", "Document");
92 structure.addDivision(documentBody);
93 this.structureSet.addStructure(structure);
94 documentBody.addFileReference(metsFile.getID());
95 documentBody.addMetadataReference("DM1");
96 }
97
98 /**
99 * Set the identified for the document. Every document should have
100 * a document number set on its accession, either through metadata
101 * placed upon it internally or externally, or by assignment through
102 * a <code>DocumentIDFactory</code>. Each identifier should be
103 * unique.
104 *
105 * @param <code>DocumentID</code> the document identifier - in XML
106 * terms, the gsdl3:id element.
107 */
108 public void setID(DocumentID id)
109 { this.id = id;
110 this.isModified = true;
111 }
112
113 /**
114 * Get the document identifier - this should be unique to the document,
115 * but care must be taken in the configuration of the collection to
116 * ensure that this is the case.
117 *
118 * @return <code>DocumentID</code> the identifer
119 */
120 public DocumentID getID()
121 { return this.id;
122 }
123
124 /**
125 * Indicate whether this document is indexed.
126 *
127 * @see: DocumentInterface.isIndexed
128 */
129 public boolean isIndexed()
130 { return true;
131 }
132
133 /**
134 * Get the date that this file was modified
135 */
136 public long getFilesDatestamp()
137 { return this.fileSet.getModifiedDatestamp();
138 }
139
140 /**
141 * Get the date that this file was modified
142 */
143 public long getModifiedDatestamp()
144 { if (this.modifiedDate == null) {
145 this.setModifiedDatestamp();
146 }
147 return this.modifiedDate.getTime();
148 }
149
150 /**
151 * Update/set the date of the most recent file modification
152 */
153 public void setModifiedDatestamp()
154 { this.modifiedDate = new java.sql.Timestamp(this.fileSet.getModifiedDatestamp());
155 }
156
157 /**
158 * Get the date that this document was first indexed
159 */
160 public long getAccessionDate()
161 { return this.firstDate.getTime();
162 }
163
164 /**
165 * Get the date that this document was last indexed
166 */
167 public long getLastIndexedDate()
168 { return this.indexDate.getTime();
169 }
170
171 /**
172 * Set the last indexed date for this document;
173 */
174 public void setLastIndexedDate(long timestamp)
175 { this.indexDate = new java.sql.Timestamp(timestamp);
176 }
177
178 /**
179 * Check if this document is in the database already.
180 *
181 * In this simple implementation, the first file in the document's "default"
182 * filegroup is taken to be the canonical file for this document - any document
183 * of the same type with the same canonical file is taken to be a match.
184 *
185 * @return <code>boolean</code> - if a matching document is found in the
186 * database.
187 */
188 public String getDuplicateID(GS3SQLConnection connection)
189 { //String query = "SELECT * FROM document INNER JOIN filegroups ON document.docId=filegroups.docId WHERE DocType=\"" + HTML_DOCUMENT_TYPE + "\"";
190
191 // Query for documents using the same file...
192 String query = "SELECT DocID FROM files INNER JOIN filegroups ON files.FileGroupRef=filegroups.FileGroupRef WHERE (filegroups.FileGroupId=\"default\" AND files.FileLocation=\"" + this.fileSet.getFile(0).getLocation().toString() + "\")";
193 try {
194 Statement statement = connection.createStatement();
195 ResultSet results = statement.executeQuery(query);
196
197 List docs = new ArrayList();
198
199 if (results.first()) {
200 do {
201 String value = results.getString("DocID");
202 docs.add(value);
203 } while (results.next());
204
205 Iterator docIterator = docs.iterator();
206 while (docIterator.hasNext()) {
207 String docId = docIterator.next().toString();
208 String innerQuery = "SELECT * FROM document WHERE DocID=\"" + docId + "\"";
209 results = statement.executeQuery(innerQuery);
210 if (results.first()) {
211 String docType = results.getString("DocType");
212 if (docType.equals(this.getDocumentType())) {
213 return docId;
214 }
215 }
216 }
217 }
218 statement.close();
219 }
220 catch (java.sql.SQLException sqlEx) {
221 System.err.println("AbstractDocument.getDuplicateID(): "+sqlEx);
222 }
223
224 return "";
225 }
226
227 /**
228 * Obtain the METS header of this document
229 *
230 * @return <code>METSHeader</code> the header
231 */
232 public METSHeader getHeader()
233 { return this.header;
234 }
235
236 /**
237 * Set the METS header for this document.
238 *
239 * @param <code>METSHeader</code> the header
240 */
241 public void setHeader(METSHeader header)
242 { this.header = header;
243 }
244
245 /**
246 * A simple implementation of the isDocumentType function that does <b>not</b> consider
247 * inheritance - it <code>must</code> be extended as required.
248 */
249 public boolean isDocumentType(String type)
250 { return type.equals(this.getDocumentType());
251 }
252
253 public abstract String getDocumentType();
254
255 public abstract String getDocumentText();
256
257 public abstract String getSectionText(String sectionId);
258
259 public String getMETSType()
260 { return "document";
261 }
262
263 /**
264 * @see DocumentInterface:addDocumentMetadata
265 */
266 public void addDocumentMetadata(MetadataLabel label, String value)
267 { // no need to set isModified, as the following call will do it anyway!
268 this.addDocumentMetadata(label.getNamespace(), label.getLabel(), value);
269 }
270
271 /**
272 * @see DocumentInterface:addDocumentMetadata
273 */
274 public void setDocumentMetadata(MetadataLabel label, String value)
275 { // no need to set isModified, as the following call will do it anyway!
276 this.setDocumentMetadata(label.getNamespace(), label.getLabel(), value);
277 }
278
279 /**
280 * @see DocumentInterface:addDocumentMetadata
281 */
282 public void addDocumentMetadata(String namespace, String label, String value)
283 { this.metadata.addMetadata("default", namespace, label, value);
284 this.isModified = true;
285 }
286
287 /**
288 * @see DocumentInterface:addDocumentMetadata
289 */
290 public void setDocumentMetadata(String namespace, String label, String value)
291 { this.metadata.setMetadata("default", namespace, label, value);
292 this.isModified = true;
293 }
294
295 /**
296 * @see DocumentInterface:removeDocumentMetadata
297 */
298 public void removeDocumentMetadata(String namespace, String label)
299 { this.metadata.removeMetadata("default", namespace, label);
300 this.isModified = true;
301 }
302
303 /**
304 *
305 */
306 public void removeAllMetadata(String namespace, String label)
307 { this.metadata.removeAllMetadata(namespace, label);
308 this.isModified = true;
309 }
310
311 /**
312 * Post metadata to a file in this document - the appropriate changes
313 * should be made...
314 */
315 public void postFileMetadata(URL fileLocation, String namespace, String label, String value)
316 {
317 // First get the list of file groups, etc. that this file is associated with...
318 List fileGroups = this.fileSet.findGroups(fileLocation);
319
320 // Next, get the METS divisions associated with each file group...
321 List divisions = this.structureSet.findDivisionsForFiles(fileGroups);
322
323 // Finally, post the metadata to the metadata group associated with each structure
324 Iterator divisionIter = divisions.iterator();
325 while (divisionIter.hasNext())
326 { METSDivision division = (METSDivision) divisionIter.next();
327
328 // get the open namespace for this division
329 METSNamespace namespaceMetadata = division.findNamespace(namespace, true, this.metadata);
330
331 // then post the metadata to it...
332 namespaceMetadata.addMetadata(label, value);
333 }
334 }
335
336 /**
337 * Get the metadata structure of the document
338 *
339 * @return <code>METSDescriptive</code> the metadata holder for the document.
340 */
341 public METSDescriptiveSet getDocumentMetadata()
342 { return this.metadata;
343 }
344
345 /**
346 * Set the metadata structure for this document
347 *
348 * @param <code>METSDescriptive</code> the new metadata holder for the document.
349 */
350 public void setDocumentMetadata(METSDescriptiveSet metadata)
351 { this.metadata = metadata;
352 this.isModified = true;
353 }
354
355 /**
356 * Get the metadata structure of the document
357 *
358 * @return <code>METSStructureSet</code> the metadata holder for the document.
359 */
360 public METSStructureSet getDocumentStructure()
361 { return this.structureSet;
362 }
363
364 public void setDocumentStructure(METSStructureSet structureSet)
365 { this.structureSet = structureSet;
366 }
367
368 /**
369 * Get the values associated with a particular metadata value.
370 *
371 * @param <code>String</code> the namespace to find the values in.
372 * @param <code>String</code> the label to match to find the values.
373 *
374 * @return <code>List</code> the values.
375 */
376 public List getDocumentMetadataItem(String namespace, String label)
377 { return this.metadata.getMetadata("default", namespace, label);
378 }
379
380 /**
381 * Get the values associated with a particular metadata value.
382 *
383 * @param <code>String</code> the namespace and label separated by a
384 * colon.
385 *
386 * @return <code>List</code> the values.
387 */
388 public List getDocumentMetadataItem(String namespaceLabel)
389 { String namespace, label;
390
391 int colonAt = namespaceLabel.indexOf(':');
392 if (colonAt < 0)
393 { namespace = GSDL3Namespace.GSDL3_NAMESPACE_ID;
394 label = namespaceLabel;
395 }
396 else
397 { namespace = namespaceLabel.substring(0, colonAt);
398 label = namespaceLabel.substring(colonAt+1);
399 }
400 return this.metadata.getMetadata("default", namespace, label);
401 }
402
403 /**
404 * @see DocumentInterface:getDocumentFiles
405 */
406 public METSFileSet getDocumentFiles()
407 { return this.fileSet;
408 }
409
410 public void setDocumentFiles(METSFileSet fileSet)
411 { this.fileSet = fileSet;
412 }
413
414 /**
415 * This is just a dummy function that does nothing at this level...
416 */
417 public org.w3c.dom.Document getDOMDocument()
418 { return null;
419 }
420
421 /**
422 * @see DocumentInterface:isMETSCompatible
423 */
424 public boolean isMETSCompatible()
425 { return true;
426 }
427
428 /**
429 * Use a default document writer - this may be overridden for subclasses...
430 *
431 * @see DocumentInterface:writeMETSObject
432 */
433 public DocumentWriter getMETSWriter()
434 { return new DocumentWriter();
435 }
436
437 /**
438 * Use a default SQL document writer - this may be overridden for subclasses...
439 *
440 */
441 public DocumentSQLWriter getSQLWriter()
442 { return new DocumentSQLWriter();
443 }
444
445 /**
446 * Obtain a document from the SQL database
447 */
448 public static AbstractDocument readSQL(GS3SQLConnection connection, ResultSet sqlResult)
449 { try {
450 DocumentID id = new DocumentID(sqlResult.getString("DocID"));
451 String type = sqlResult.getString("docType");
452
453 // Use a factory method to create the correct subtype...
454 AbstractDocument document = DocumentFactory.createDocument(type, id);
455 // Append the document date information
456 document.indexDate = sqlResult.getTimestamp("IndexedDate");
457 document.firstDate = sqlResult.getTimestamp("AccessionDate");
458 document.modifiedDate = sqlResult.getTimestamp("ModifiedDate");
459
460 // Get the individual components of the document
461 METSFileSet fileSet = METSFileSet.readSQL(document, connection);
462 document.setDocumentFiles(fileSet);
463 METSDescriptiveSet descriptiveSet = METSDescriptiveSet.readSQL(document, connection);
464 document.setDocumentMetadata(descriptiveSet);
465 METSStructureSet structureSet = METSStructureSet.readSQL(document, connection);
466 document.setDocumentStructure(structureSet);
467
468 // indicate that the document is not currently modified
469 document.setChanged(false);
470 return document;
471 }
472 catch (SQLException sqlEx) {
473 System.err.println("AbstractDocument.readSQL(): Failure to load document: " + sqlEx);
474 }
475 return null;
476 }
477
478 /**
479 *
480 */
481 public boolean isChanged()
482 { return this.isModified;
483 }
484
485 public void setChanged(boolean isModified)
486 { this.isModified = isModified;
487 }
488}
Note: See TracBrowser for help on using the repository browser.