source: branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/gs3build/metadata/METSStructure.java@ 9858

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

OK, changed my mind about making SQLConnection kill off the previous statement.
To make it more transparent what is happening, you now have to create a Statement (connection.createStatement()), then use the Statement to execute the query. This means that the thing doing the query owns the Statement, and can kill it off when finished with it, and nothing else can kill it off unexpectedly. The previous way this was all implemented meant that there was a large memory leak, and some functionality actually relied on this. A newer version of the mysql connector/J has fixed the bug where the statement wasn't closed on garbage collection, but it still seems better to close it explicitly.
Hopefully I have got it all back to working as well as it was bfore, and haven't introduced any bugs :-)

  • Property svn:keywords set to Author Date Id Revision
File size: 9.6 KB
Line 
1package org.greenstone.gsdl3.gs3build.metadata;
2
3import java.io.PrintWriter;
4
5import java.util.List;
6import java.util.ArrayList;
7import java.util.Map;
8import java.util.LinkedHashMap;
9import java.util.Iterator;
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.DocumentInterface;
19
20import org.greenstone.gsdl3.gs3build.util.XMLTools;
21import org.greenstone.gsdl3.gs3build.database.*;
22
23public class METSStructure extends AbstractStructure
24{
25 String label;
26 String type;
27 METSDivision divGroup;
28
29 public static final String STRUCTURE_TYPE = "Structure";
30
31 public METSStructure(String id, String label, String type)
32 {
33 super(id);
34
35 this.label = label;
36 this.type = type;
37 this.divGroup = null;
38 }
39
40 /**
41 * Show what sort of <code>AbstractStructure</code> this structure is...
42 *
43 * @return <code>String The identifying string for a <code>METSStructure</code> type.
44 */
45 public String getStructureType()
46 { return STRUCTURE_TYPE;
47 }
48
49 /**
50 * Find all the divisions that match a given list of file group
51 * identifiers...
52 *
53 * @param <code>List</code> the list of identifiers to find
54 * @param <code>List</code> the list into which to place any
55 * matching identifiers.
56 */
57 public void findDivisionsForFiles(List listOfFileIdentifiers, List resultList)
58 { Iterator groups = this.children.values().iterator();
59 while (groups.hasNext())
60 { METSDivision group = (METSDivision) groups.next();
61
62 group.findDivisionsForFiles(listOfFileIdentifiers, resultList);
63 }
64 }
65
66 /**
67 * Add a division further into this structure.
68 *
69 * @param <code>String</code> the identifier label for the division
70 * within which the division is to be added.
71 * @param <code>METSDivision</code> the division to add.
72 */
73 public void addSubDivision(String divisionLabel, METSDivision division)
74 { String topDivision = METSDivision.getTopDivisionName(divisionLabel);
75
76 METSDivision child = (METSDivision) this.children.get(topDivision);
77 if (child == null)
78 { return;
79 }
80
81 child = child.getDivision(divisionLabel);
82
83 if (child != null) {
84 child.addDivision(division);
85 }
86 }
87
88 /**
89 * Get a subdivision of a given identifier...
90 *
91 * @param <code>String</code> the identifier of the division
92 * @return <code>METSDivision</code> the division, which will be
93 * <code>null</code> if it is not found.
94 */
95 public METSDivision getDivision(String divisionLabel)
96 { String topDivision = METSDivision.getTopDivisionName(divisionLabel);
97
98 if (!topDivision.equals("All"))
99 System.out.println("Top division is " + topDivision);
100 METSDivision child = (METSDivision) this.children.get(topDivision);
101 if (child == null)
102 { System.out.println("No child found");
103 Iterator groups = this.children.keySet().iterator();
104 while (groups.hasNext()) {
105 System.out.println(groups.next().toString());
106 }
107 return null;
108 }
109
110
111 child = child.getDivision(divisionLabel);
112
113 return child;
114 }
115
116
117 /*
118 *
119 * parse an XML Element as a METSStructure Section
120 *
121 * @param <code>Element</code> the XML element which represents
122 * the mets:structMap itself
123 */
124
125 public static METSStructure parseXML(Element element)
126 {
127 String structId = element.getAttribute("ID");
128 String structLabel = element.getAttribute("LABEL");
129 String structType = element.getAttribute("TYPE");
130
131 METSStructure thisStruct = new METSStructure (structId, structLabel, structType);
132
133 NodeList divSecs = element.getChildNodes();
134 if (divSecs != null) {
135 for (int c = 0; c < divSecs.getLength(); c++) {
136 if (divSecs.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE){
137 continue;
138 }
139 Element divElement = (Element) divSecs.item(c);
140 String divName = divElement.getNodeName();
141 if (divName.equals("mets:div")) {
142 METSDivision division = METSDivision.parseXML(divElement);
143 thisStruct.addDivision(division);
144 } else {
145 System.err.println("Error: mets:structMap was expecting mets:div but got "+divName);
146 }
147 }
148 }
149 return thisStruct;
150 }
151
152 /**
153 * Write this structure in XML(METS) format to a <code>PrintWriter</code>
154 */
155 public void write(PrintWriter writer)
156 {
157 Iterator groups = this.children.values().iterator();
158
159 String tag = XMLTools.getOpenTag("mets", "structMap");
160 tag = XMLTools.addAttribute(tag, "ID", this.ID.toString());
161 tag = XMLTools.addAttribute(tag, "TYPE", this.type);
162 tag = XMLTools.addAttribute(tag, "LABEL", this.label);
163
164 writer.println(tag);
165 while (groups.hasNext()){
166 METSDivision group = (METSDivision) groups.next();
167
168 group.write(writer);
169 }
170 writer.println("</mets:structMap>");
171 }
172
173
174 /**
175 * Write this METSStructure to an SQL database....
176 *
177 * @param <code>DocumentInterface</code> the enclosing document.
178 * @param <code>GS3SQLConnection</code> the SQL database connection.
179 */
180 public boolean writeSQL(DocumentInterface document, GS3SQLConnection connection)
181 {
182 int sqlRef = -1;
183 ResultSet results = null;
184 Statement statement = null;
185
186 // Prepare query to see if this structure has already been written
187 GS3SQLSelect select = new GS3SQLSelect("structure");
188 select.addField("StructureRef");
189 GS3SQLWhereItem whereItem = new GS3SQLWhereItem("DocID", "=", document.getID().toString());
190 GS3SQLWhereItem item = new GS3SQLWhereItem("StructureID", "=", this.ID.toString());
191 GS3SQLWhere where = new GS3SQLWhere(whereItem);
192 where.add(item);
193 select.setWhere(where);
194
195 // attempt to execute the query & get the current structure's reference
196 try {
197 statement = connection.createStatement();
198 results = statement.executeQuery(select.toString());
199 if (results.first()){
200 sqlRef = results.getInt("structureRef");
201 }
202 }
203 catch (SQLException sqlEx) {
204 System.err.print("METSStructure.writeSQL(): "+sqlEx);
205 return false;
206 }
207
208 // insert a new structure if it wasn't there previously
209 if (sqlRef == -1) {
210 GS3SQLInsert insert = new GS3SQLInsert("structure");
211 insert.addValue("DocID", document.getID().toString());
212 insert.addValue("StructureID", this.ID.toString());
213 insert.addValue("StructureType", this.type);
214 insert.addValue("Label", this.label);
215
216 try {
217 statement.execute(insert.toString());
218
219 // get the new structure reference by re-running the original select object
220 results = statement.executeQuery(select.toString());
221 if (results.first()) {
222 sqlRef = results.getInt("StructureRef");
223 }
224 } catch (SQLException sqlEx) {
225 System.err.print("METSStructure.writeSQL(): "+sqlEx);
226 return false;
227 }
228
229 }
230 else {
231 GS3SQLUpdate update = new GS3SQLUpdate("structure");
232 update.setWhere(where);
233
234 update.addValue("StructureType", this.type);
235 update.addValue("Label", this.label);
236
237 try {
238 statement.execute(update.toString());
239 } catch (SQLException sqlEx) {
240 System.err.print("METSStructure.writeSQL(): "+sqlEx);
241 return false;
242 }
243 }
244
245 // close the statement
246 try {
247 statement.close();
248 } catch (SQLException e) {
249 System.err.println("METSStructure.writeSQL(): "+e);
250 }
251 // write out the child groups (Divisions) now...
252 Iterator groups = this.children.values().iterator();
253
254 while (groups.hasNext()){
255 METSDivision group = (METSDivision) groups.next();
256
257 if (!group.writeSQL(document.getID(), sqlRef, true, connection)){
258 return false;
259 }
260 }
261 return true;
262 }
263
264 /**
265 * Read a METSStructure from a database - on entry, the current item in the
266 * <code>ResultSet</code> holds the row in the database with the structure's
267 * data.
268 *
269 * @param <code>DocumentInterface</code> the document which owns the structure
270 * @param <code>GS3SQLConnection</code> the database connection itself, to load
271 * child objects through, etc.
272 * @param <code>ResultSet</code> pointing to the current row in the database.
273 */
274 public static METSStructure readSQL(DocumentInterface document, GS3SQLConnection connection,
275 ResultSet resultSet)
276 {
277 GS3SQLSelect select = null;
278
279 try {
280 String ID = resultSet.getString("StructureID");
281 String type = resultSet.getString("StructureType");
282 String label = resultSet.getString("Label");
283
284 // create the metadata block object
285 METSStructure structure = new METSStructure(ID, label, type);
286
287 // get its metadata reference to retrieve divisions
288 int structureRef = resultSet.getInt("StructureRef");
289
290 // query the database for matching division for this structure block
291 select = new GS3SQLSelect("divisions");
292 select.addField("*");
293 GS3SQLWhereItem whereItem = new GS3SQLWhereItem("ParentRef", "=", Integer.toString(structureRef),
294 GS3SQLField.INTEGER_TYPE);
295 GS3SQLWhere where = new GS3SQLWhere(whereItem);
296 whereItem = new GS3SQLWhereItem("ParentType", "=", METSStructure.STRUCTURE_TYPE);
297 where.add(whereItem);
298 select.setWhere(where);
299
300 Statement statement = connection.createStatement();
301 ResultSet divisionSet = statement.executeQuery(select.toString());
302
303 // parse through the divisions
304 if (divisionSet.first()) {
305 do {
306 METSDivision division = METSDivision.readSQL(connection, divisionSet);
307 if (division != null) {
308 structure.addDivision(division);
309 }
310 }
311 while (divisionSet.next());
312 }
313 statement.close();
314 return structure;
315 }
316 catch (SQLException sqlEx) {
317 System.err.println("METSStructure.readSQL(): "+ sqlEx + " " + select.toString());
318 System.exit(1);
319 }
320 return null;
321 }
322}
323
Note: See TracBrowser for help on using the repository browser.