source: trunk/gsdl3/src/java/org/greenstone/gsdl3/gs3build/metadata/METSDescriptive.java@ 5800

Last change on this file since 5800 was 5800, checked in by cs025, 20 years ago

Adding gs3build

  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 KB
Line 
1package org.greenstone.gsdl3.gs3build.metadata;
2
3import java.util.List;
4import java.util.ArrayList;
5import java.util.Iterator;
6
7import java.io.PrintWriter;
8
9import java.sql.SQLException;
10
11import org.w3c.dom.Document;
12import org.w3c.dom.Element;
13import org.w3c.dom.NamedNodeMap;
14import org.w3c.dom.Node;
15import org.w3c.dom.NodeList;
16import org.w3c.dom.Text;
17
18import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
19
20import org.greenstone.gsdl3.gs3build.util.XMLTools;
21import org.greenstone.gsdl3.gs3build.util.GS3SQLConnection;
22import org.greenstone.gsdl3.gs3build.database.*;
23
24/**
25 * Support the descriptive metadata of a given document
26 *
27 * The descriptive metadata can occur multiple times, so this 'wrapper' is
28 * in fact a holder for a number of individual metadata sets. Individual
29 * metadata groups are found in METSNamespace items.
30 *
31 *
32 */
33
34import org.greenstone.gsdl3.gs3build.util.MultiMap;
35
36public class METSDescriptive
37{ MultiMap map;
38 String ID;
39 String name;
40
41 public METSDescriptive(String ID, String name)
42 { this.map = new MultiMap();
43 this.ID = ID;
44 this.name = name;
45 }
46
47 public String getID()
48 { return this.ID;
49 }
50
51 public String getName()
52 { return this.name;
53 }
54
55 public void addNamespace(METSNamespace namespace)
56 { this.map.put(namespace.getName(), namespace);
57 }
58
59 public METSNamespace getNamespace(String namespace)
60 { return (METSNamespace) this.map.get(namespace);
61 }
62
63 /**
64 * Get the version of a metadata namespace that can be used for
65 * adding new values to the document. Remember, each namespace may
66 * occur more than once, but only one of the occurrences can be 'open'.
67 *
68 * @param <code>String</code> the name of the namespace
69 */
70 public METSNamespace getOpenNamespace(String namespace)
71 { if (this.map.getAll(namespace) == null)
72 { return null;
73 }
74
75 Iterator namespaces = ((List) this.map.getAll(namespace)).iterator();
76
77 while (namespaces.hasNext())
78 { METSNamespace namespaceData = (METSNamespace) namespaces.next();
79
80 if (namespaceData.isEditable())
81 { return namespaceData;
82 }
83 }
84 return null;
85 }
86
87 /**
88 * Add a piece of metadata to this document. Existing values are preserved.
89 *
90 * @param <code>String</code> the namespace in which the metadata occurs
91 * @param <code>String</code> the label of the metadata
92
93 * @param <code>String</code> the value of the metadata
94 */
95 public void addMetadata(String namespace, String label, String value)
96 { METSNamespace namespaceData = this.getOpenNamespace(namespace);
97
98 if (namespaceData == null ||
99 namespaceData.isEditable() == false)
100 { namespaceData = NamespaceFactory.initNamespace(namespace);
101 this.addNamespace(namespaceData);
102 }
103 namespaceData.addMetadata(label, value);
104 }
105
106 /**
107 * Add a piece of metadata to this document. Existing values in editable
108 * parts of the document's metadata are destroyed.
109 *
110 * @param <code>String</code> the namespace in which the metadata occurs
111 * @param <code>String</code> the label of the metadata
112
113 * @param <code>String</code> the value of the metadata
114 */
115 public void setMetadata(String namespace, String label, String value)
116 { METSNamespace namespaceData = this.getOpenNamespace(namespace);
117
118 if (namespaceData == null ||
119 namespaceData.isEditable() == false)
120 { namespaceData = NamespaceFactory.initNamespace(namespace);
121 this.addNamespace(namespaceData);
122 }
123 namespaceData.setMetadata(label, value);
124 }
125
126 /**
127 * Fetch a <code>List</code> of the values matching the given label in
128 * the requisite namespace.
129 *
130 * @param <code>String</code> namespace
131 * @param <code>String</code> label of metadata to match
132 *
133 * @return <code>List</code> the corresponding values found.
134 */
135 public List getMetadata(String namespace, String label)
136 {
137 // Simple case - no metadata
138 if (!this.map.containsKey(namespace))
139 { return null;
140 }
141
142 // if there's just one instance of the requisite namespace,
143 // then again it is a simple case
144 if (this.map.getAll(namespace).size() == 1)
145 { return this.getNamespace(namespace).getMetadata(label);
146 }
147
148 // otherwise, step through and accumulate
149 List accumulatedValues = new ArrayList();
150 Iterator namespaceIterator = this.map.getAll(namespace).iterator();
151 while (namespaceIterator.hasNext())
152 { METSNamespace localNamespace = (METSNamespace) namespaceIterator.next();
153
154 List localList = localNamespace.getMetadata(label);
155 if (localList != null && localList.size() > 0)
156 { accumulatedValues.addAll(localList);
157 }
158 }
159
160 // if the result of the accumulation is empty, return a null item
161 if (accumulatedValues.size() == 0)
162 { return null;
163 }
164
165 return accumulatedValues;
166 }
167
168 /**
169 * Parse an XML Element as a METS Descriptive Metadata section
170 *
171 * @param <code>Element</code> the XML element which represents the dmdSec itself
172 */
173 public static METSDescriptive parseXML(Element element)
174 { // Note: no parsing of attributes required, we just move onto the metadata
175 // namespaces/sections themselves
176 String ID = element.getAttribute("ID");
177 String label = element.getAttribute("GROUPID");
178 METSDescriptive thisDescriptive = new METSDescriptive(ID, label);
179
180 NodeList children = element.getChildNodes();
181
182 for (int c = 0; c < children.getLength(); c ++)
183 { if (children.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE) {
184 continue;
185 }
186
187 Element childElement = (Element) children.item(c);
188 if (childElement.getNodeName().equals("mets:mdRef"))
189 { METSNamespace namespace = NamespaceFactory.parseXML(element);
190 }
191 else if (childElement.getNodeName().equals("mets:mdWrap"))
192 { METSNamespace namespace = NamespaceFactory.parseXML(element);
193 }
194 else
195 { // TODO: raise an error!
196 }
197 }
198 return thisDescriptive;
199 }
200
201
202 /**
203 * Write the document metadata to a <code>PrintWriter</code> in METS
204 * XML format.
205 *
206 * @param <code>PrintWriter</code> the writer to use for output
207 */
208 public void write(PrintWriter output)
209 { String tag = XMLTools.getOpenTag("mets", "dmdSec");
210 tag = XMLTools.addAttribute(tag, "ID", this.ID);
211 tag = XMLTools.addAttribute(tag, "GROUPID", this.name);
212 output.println(tag);
213
214 Iterator keys = this.map.keySet().iterator();
215
216 // get the keys one by one
217 while (keys.hasNext())
218 { Object nextKey = keys.next();
219 if (nextKey == null)
220 { continue;
221 }
222 String key = nextKey.toString();
223
224 // get every copy of the current namespace name - namespaces may
225 // occur more than once, so this is a List
226 Iterator namespaces = this.map.getAll(key).iterator();
227
228 // namespaces will write themselves...
229 while (namespaces.hasNext())
230 { METSNamespace namespace = (METSNamespace) namespaces.next();
231
232 namespace.write(output);
233 }
234 }
235
236 tag = XMLTools.getCloseTag("mets", "dmdSec");
237 output.println(tag);
238 }
239
240 public void writeSQL(DocumentInterface document, GS3SQLConnection connection)
241 { // check if this node is in the
242 int sqlId = 0;
243
244 // System.out.println("Writing " + connection.toString());
245
246 GS3SQLSelect select = new GS3SQLSelect("metadata");
247 select.addField("*");
248 GS3SQLWhereItem whereItem = new GS3SQLWhereItem("MetaID", "=", this.ID);
249 GS3SQLWhereItem item = new GS3SQLWhereItem("DocID", "=", document.getID().toString());
250 GS3SQLWhere where = new GS3SQLWhere(whereItem);
251 where.add(item);
252 select.setWhere(where);
253
254 connection.execute(select.toString());
255 try {
256 if (connection.getResultSet() != null &&
257 connection.getResultSet().next()) {
258 // the node already exists - no need to do anything as such
259 }
260 else
261 {
262 // It is a new node and needs writing
263 GS3SQLInsert insert = new GS3SQLInsert("metadata");
264 insert.addValue("DocID", document.getID().toString());
265 insert.addValue("MetaID", this.ID);
266
267 connection.execute(insert.toString());
268
269 // now execute the select statement again to get the new identifier
270 // 'MetadataRef'
271 // System.out.println(select.toString());
272 connection.execute(select.toString());
273 }
274
275 // get the reference for this item...
276 connection.getResultSet().first();
277 sqlId = connection.getResultSet().getInt("MetadataRef");
278 }
279 catch (SQLException sql)
280 { System.out.println(sql);
281 }
282
283 Iterator keys = this.map.keySet().iterator();
284
285 // get the keys one by one
286 while (keys.hasNext())
287 { Object nextKey = keys.next();
288 if (nextKey == null)
289 { continue;
290 }
291 String key = nextKey.toString();
292
293 // get every current namespace - namespaces may
294 // occur more than once, so this is a List
295 Iterator namespaces = this.map.getAll(key).iterator();
296
297 // namespaces will write themselves...
298 while (namespaces.hasNext())
299 { METSNamespace namespace = (METSNamespace) namespaces.next();
300
301 namespace.writeSQL(sqlId, connection);
302 }
303 }
304 }
305}
Note: See TracBrowser for help on using the repository browser.