source: trunk/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/SimpleNamespace.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: 10.7 KB
Line 
1package org.greenstone.gsdl3.gs3build.metadata;
2
3import java.io.PrintWriter;
4import java.util.Iterator;
5import java.util.List;
6import java.util.Map;
7import java.util.ArrayList;
8import java.util.HashMap;
9
10import java.sql.SQLException;
11import java.sql.Statement;
12import java.sql.ResultSet;
13
14import org.w3c.dom.Document;
15import org.w3c.dom.Element;
16import org.w3c.dom.NamedNodeMap;
17import org.w3c.dom.Node;
18import org.w3c.dom.NodeList;
19import org.w3c.dom.Text;
20
21import org.greenstone.gsdl3.gs3build.util.MultiMap;
22import org.greenstone.gsdl3.gs3build.util.XMLTools;
23import org.greenstone.gsdl3.gs3build.database.*;
24
25/**
26 * Implement a simple, unordered, namespace in METS.
27 *
28 * @see: org.greenstone.gsdl3.gs3build.metadata.METSNamespace
29 */
30
31public class SimpleNamespace extends METSNamespace
32{
33 MultiMap metadataMap;
34
35 public SimpleNamespace(String name)
36 {
37 super(name);
38 this.metadataMap = new MultiMap();
39 }
40
41 public SimpleNamespace(String name, METSLocation location)
42 {
43 super(name, location);
44 this.metadataMap = new MultiMap();
45 }
46
47 public SimpleNamespace(String name, Element mdWrapTag)
48 {
49 super(name);
50 this.metadataMap = new MultiMap();
51
52 NodeList childNodes = mdWrapTag.getChildNodes();
53 for (int c = 0; c < childNodes.getLength(); c ++) {
54 // a metadata node
55 if (childNodes.item(c).getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
56 // get the name of the metadata from the node
57 String metadataLabel = childNodes.item(c).getNodeName();
58
59 // skip blank labels
60 // TODO: raise an error: metadata item without metadata label set
61 if (metadataLabel == null || metadataLabel.length() == 0) {
62 continue;
63 }
64
65 // build the value
66 String metadataValue = "";
67
68 Element childElement = (Element) childNodes.item(c);
69 for (int i = 0; i < childElement.getChildNodes().getLength(); i ++) {
70 metadataValue = metadataValue + childElement.getChildNodes().item(i).toString();
71 }
72
73 // trim any leading namespace identifiers in "namespace:label" metadata
74 if (metadataLabel.startsWith(this.name + ":")) {
75 metadataLabel = metadataLabel.substring(this.name.length() + 1);
76 }
77
78 this.addMetadata(metadataLabel, metadataValue);
79 }
80 }
81 }
82
83 public boolean validate(String field, String value)
84 {
85 return true;
86 }
87
88 /**
89 * Add a metadata item. Whether the field and value validate for this
90 * schema will also be tested.
91 *
92 * @param <code>String</code> the name of the field to be given the value
93 * @param <code>String</code> the value to be assigned
94 *
95 * @return <code>boolean</code> whether the field value was added. This
96 * would return <code>false</code> if the values did not validate,
97 * for example.
98 */
99 public boolean addMetadata(String label, String value)
100 {
101 if (!this.validate(label, value)) {
102 return false;
103 }
104
105 this.metadataMap.put(label, value);
106 return true;
107 }
108
109 /**
110 * Assign a metadata item. Whether the field and value validate for this
111 * schema will also be tested. Any existing metadata for that field will
112 * be destroyed if the new value validates.
113 *
114 * @param <code>String</code> the name of the field to be given the value
115 * @param <code>String</code> the value to be assigned
116 *
117 * @return <code>boolean</code> whether the field value was added. This
118 * would return <code>false</code> if the values did not validate,
119 * for example.
120 */
121 public boolean setMetadata(String label, String value)
122 {
123 if (!this.validate(label, value)) {
124 return false;
125 }
126
127 this.metadataMap.setOnly(label, value);
128 return true;
129 }
130
131 /**
132 * Remove all metadata values for a given field name
133 *
134 * @param <code>String</code> the field to delete
135 *
136 * @return <code>boolean</code> whether the field was actually deleted;
137 * will return <code>true</code> if the field was already empty.
138 */
139 public boolean removeMetadata(String label)
140 {
141 this.metadataMap.remove(label);
142 return true;
143 }
144
145 /**
146 * Remove a particular incidence of a given metadata field for a document.
147 * If an exact match for the given value is not found, nothing changes.
148 * N.B. if a value occurs twice, only the first incidence of it will be
149 * deleted from the list.
150 *
151 * @param <code>String</code> the field to have the value removed
152 * @param <code>String</code> the value to be removed from a given field
153 *
154 * @return <code>boolean</code> <code>true</code> if an actual metadata text
155 * is matched against the given value and is thus deleted.
156 */
157 public boolean removeMetadata(String label, String value)
158 {
159 return this.metadataMap.remove(label, value);
160 }
161
162 /**
163 * Get the metadata items for a particular label
164 *
165 * @param <code>String</code> the label to fetch values for
166 *
167 * @return <code>List</code> the list of corresponding values. May be
168 * <code>null</code>
169 */
170 public List getMetadata(String label)
171 {
172 return this.metadataMap.getAll(label);
173 }
174
175 public Iterator getMetadataNames()
176 {
177 return this.metadataMap.keySet().iterator();
178 }
179
180 /**
181 * Write out the metadata to an XML file through a <code>PrintWriter</code>.
182 *
183 * @param <code>PrintWriter</code> the writer to use.
184 */
185 public boolean write(PrintWriter writer)
186 {
187 // if this is a non-file block of metadata, write it out in long hand
188 if (this.location == null){
189 String tag = XMLTools.getOpenTag("mets", "mdWrap");
190
191 tag = XMLTools.addAttribute(tag, "MDTYPE", "OTHER");
192 tag = XMLTools.addAttribute(tag, "OTHERMDTYPE", this.name);
193 if (this.id != null) {
194 this.id = "gsdl"+this.id;
195 tag = XMLTools.addAttribute(tag, "ID", this.id);
196 }
197 writer.print(" "); //indentation
198 writer.println(tag);
199
200 tag = XMLTools.getOpenTag("mets", "xmlData");
201 writer.print(" "); //indentation
202 writer.println(tag);
203
204 Iterator keys = this.metadataMap.keySet().iterator();
205 while (keys.hasNext()){
206 String thisKey = keys.next().toString();
207 writer.print(" "); //indentation
208 this.writeItem(writer, thisKey);
209 }
210
211 writer.print(" "); //indentation
212 writer.println(XMLTools.getCloseTag("mets", "xmlData"));
213
214 writer.print(" "); //indentation
215 writer.println(XMLTools.getCloseTag("mets", "mdWrap"));
216 }
217 // otherwise, drop the metadata out in a simplified file-reference
218 // form only
219 else
220 {
221 String tag = XMLTools.getOpenTag("mets","mdRef");
222 tag = XMLTools.addAttribute(tag, "LOCTYPE", "URL");
223 tag = XMLTools.addAttribute(tag, "xlink:href", location.getLocation().toString());
224 //tag = XMLTools.addAttribute(tag, "MDTYPE", "OTHER");
225 //tag = XMLTools.addAttribute(tag, "OTHERMDTYPE", this.name);
226 tag = XMLTools.addAttribute(tag, "MDTYPE", this.name);
227 if (this.id != null) {
228 tag = XMLTools.addAttribute(tag, "ID", this.id);
229 }
230 writer.println(tag);
231 writer.print(" "); //indentation
232 writer.println("</mets:mdRef>");
233 }
234 return true;
235 }
236
237 /**
238 * Write out a single element - this may be overloaded to provide for the
239 * appropriate formatting for this metadata.
240 */
241 protected boolean writeItem(PrintWriter writer, String label)
242 {
243 if (this.location == null) {
244 // just place the metadata in a simple wrapper
245 Iterator values = this.metadataMap.getAll(label).iterator();
246
247 while (values.hasNext()) {
248 String value = values.next().toString();
249 String metaTagName = "Metadata name=" +'"'+ label +'"';
250 //writer.write(XMLTools.getOpenTag(this.name, label));
251 writer.write(XMLTools.getOpenTag(this.name, metaTagName));
252 writer.write(value);
253
254 //writer.println(XMLTools.getCloseTag(this.name, label));
255 writer.println(XMLTools.getCloseTag(this.name, "Metadata"));
256 }
257 }
258 else {
259 String tag = XMLTools.getOpenTag("mets", "mdRef");
260 tag = XMLTools.addAttribute(tag, "LOCTYPE", this.location.getType());
261 tag = XMLTools.addAttribute(tag, "xlink:href", this.location.getLocation().toString());
262 tag = XMLTools.addAttribute(tag, "MDTYPE", this.getName());
263 tag = XMLTools.makeSingleton(tag);
264 writer.print(" "); //indentation
265 writer.println(tag);
266 }
267 return true;
268 }
269
270 /**
271 * Write out the metadata to an SQL database through a <code>GS3SQLConnection</code>.
272 *
273 * @param <code>GS3SQLConnection</code> the SQL database to use.
274 */
275 public boolean writeSQL(int parentId, GS3SQLConnection connection)
276 {
277 // write the general stuff
278 String sqlId;
279
280 if (!super.writeSQL(parentId, connection)) {
281 return false;
282 }
283
284 Statement statement = null;
285 ResultSet results = null;
286 try {
287 statement = connection.createStatement();
288 if (this.id == null) {
289 GS3SQLSelect select = new GS3SQLSelect("namespaces");
290 select.setWhere(new GS3SQLWhere(new GS3SQLWhereItem("MetadataRef", "=", Integer.toString(parentId), GS3SQLField.INTEGER_TYPE)));
291 select.addField("NamespaceRef");
292 results = statement.executeQuery(select.toString());
293 if (results.first()) {
294 sqlId = Integer.toString(results.getInt("NamespaceRef"));
295 } else {
296 statement.close();
297 return false;
298 }
299 }
300 else {
301 sqlId = this.id;
302 }
303
304 // clear all the existing metadata items for this namespace
305 GS3SQLDelete delete = new GS3SQLDelete("mdvalues");
306 GS3SQLWhere where = new GS3SQLWhere(new GS3SQLWhereItem("NamespaceRef", "=", sqlId, GS3SQLField.INTEGER_TYPE));
307 delete.setWhere(where);
308 statement.execute(delete.toString());
309
310 // write out the metadata for this namespace
311 Iterator keys = this.metadataMap.keySet().iterator();
312 while (keys.hasNext()){
313 String thisKey = keys.next().toString();
314
315 Iterator values = this.metadataMap.getAll(thisKey).iterator();
316
317 while (values.hasNext()){
318 String value = values.next().toString();
319
320 GS3SQLInsert insert = new GS3SQLInsert("mdvalues");
321 insert.addValue("NamespaceRef", sqlId, GS3SQLField.INTEGER_TYPE);
322 insert.addValue("Label", thisKey);
323 insert.addValue("Value", value);
324 statement.execute(insert.toString());
325 }
326 }
327 statement.close();
328 }
329 catch (SQLException sql) {
330 System.out.println("SimpleNamespace.writeSQL(): "+sql);
331 }
332 return true;
333 }
334
335
336 /**
337 * <p>Indicate whether this metadata is open to being changed or not.</p>
338 * <p>Metadata which is created from a distinct file cannot be changed,
339 * only those which have no associated file can be modified.
340 *
341 * @return <code>boolean</code> whether this namespace can be altered.
342 */
343 public boolean isEditable()
344 {
345 return (this.location == null);
346 }
347}
Note: See TracBrowser for help on using the repository browser.