1 |
3321
|
barteau
|
/*
|
2 |
|
|
* ClientFgdcHelper.java
|
3 |
|
|
*
|
4 |
|
|
* Created on June 25, 2007, 9:58 AM
|
5 |
|
|
*
|
6 |
|
|
* To change this template, choose Tools | Template Manager
|
7 |
|
|
* and open the template in the editor.
|
8 |
|
|
*/
|
9 |
|
|
|
10 |
|
|
package edu.ucsb.nceas.metacat.clientview;
|
11 |
|
|
|
12 |
|
|
import edu.ucsb.nceas.metacat.client.MetacatException;
|
13 |
|
|
import edu.ucsb.nceas.utilities.XMLUtilities;
|
14 |
|
|
import java.io.IOException;
|
15 |
|
|
import java.io.InputStream;
|
16 |
|
|
import java.io.Reader;
|
17 |
|
|
import java.io.StringReader;
|
18 |
|
|
import java.util.HashMap;
|
19 |
|
|
import java.util.Iterator;
|
20 |
|
|
import java.util.Properties;
|
21 |
|
|
import javax.xml.xpath.XPath;
|
22 |
|
|
import javax.xml.xpath.XPathConstants;
|
23 |
|
|
import javax.xml.xpath.XPathExpressionException;
|
24 |
|
|
import javax.xml.xpath.XPathFactory;
|
25 |
|
|
import org.w3c.dom.Document;
|
26 |
|
|
import org.w3c.dom.DocumentType;
|
27 |
|
|
import org.w3c.dom.Node;
|
28 |
|
|
import org.w3c.dom.NodeList;
|
29 |
|
|
|
30 |
|
|
/**
|
31 |
|
|
*
|
32 |
|
|
* @author barteau
|
33 |
|
|
*/
|
34 |
|
|
public abstract class ClientFgdcHelper {
|
35 |
|
|
|
36 |
|
|
private static XPath xpath = XPathFactory.newInstance().newXPath();
|
37 |
|
|
|
38 |
|
|
/**
|
39 |
|
|
* Data Document ID location within an FGDC document. XPath expression.
|
40 |
|
|
*/
|
41 |
|
|
public static final String FGDC_DATA_FILE_DOCID_XPATH = "/metadata/distinfo/stdorder/digform/digtopt/onlinopt/computer/networka/networkr";
|
42 |
3372
|
barteau
|
public static final String FGDC_DATA_FILE_QUERY_XPATH = FGDC_DATA_FILE_DOCID_XPATH + "[text()='%1s']";
|
43 |
3482
|
barteau
|
public static final String FGDC_DATA_FILE_NAME_XPATH = "digtinfo/formcont";
|
44 |
3321
|
barteau
|
|
45 |
3482
|
barteau
|
/**
|
46 |
|
|
* FGDC Data Document ID location within an FGDC document, relative to the "distinfo" parent node.
|
47 |
|
|
* XPath expression.
|
48 |
|
|
*/
|
49 |
|
|
public static final String FGDC_DATA_FILE_NODES_XPATH = "stdorder/digform/digtopt/onlinopt/computer/networka/networkr";
|
50 |
|
|
|
51 |
3367
|
barteau
|
public static final String PATH4ANCESTOR = FGDC_DATA_FILE_DOCID_XPATH + "[text()='%1s']/ancestor::node()[name()='%2s']";
|
52 |
3516
|
barteau
|
public static final String SUB_DOCS_PATH = FGDC_DATA_FILE_DOCID_XPATH + "/text()";
|
53 |
3321
|
barteau
|
|
54 |
|
|
/**
|
55 |
|
|
* Metadata Document ID location within an FGDC document. XPath expression.
|
56 |
|
|
*/
|
57 |
|
|
public static final String FGDC_DOCID_XPATH = "/metadata/distinfo/resdesc";
|
58 |
3482
|
barteau
|
public static final String FGDC_FILE_NAME_XPATH = "custom";
|
59 |
3372
|
barteau
|
/**
|
60 |
|
|
* Metadata Document ID query template within an FGDC document. Substitute %1s with Doc Id.
|
61 |
|
|
*/
|
62 |
3367
|
barteau
|
public static final String XPATH_QUERY_TEMPLATE = FGDC_DOCID_XPATH + "[text()='%1s']";
|
63 |
3482
|
barteau
|
public static final String FGDC_DOCID_ROOT_XPATH = XPATH_QUERY_TEMPLATE + "/ancestor::node()[name()='distinfo']";
|
64 |
3321
|
barteau
|
|
65 |
|
|
/**
|
66 |
|
|
* Identifies the FGDC DTD.
|
67 |
|
|
*/
|
68 |
|
|
public static final String FGDC_SYSTEM_ID = "http://www.fgdc.gov/metadata/fgdc-std-001-1998.dtd";
|
69 |
|
|
|
70 |
|
|
/**
|
71 |
|
|
* Handles a client's request to delete a document.
|
72 |
|
|
* If its a data document, it removes the Doc Id from the FGDC metadata in the
|
73 |
|
|
* Metacat database. It determines what metadata Doc ID is including this Doc Id.
|
74 |
|
|
* It then queries metacat for the parent FGDC document and removes the Doc Id from it, and
|
75 |
|
|
* reloads the new version with a new revision number.
|
76 |
|
|
* If its a metadata document, it deletes any related data documents, then it
|
77 |
|
|
* deletes the metadata. In either instance, it sets the server feedback in
|
78 |
|
|
* the session ("updateFeedback").
|
79 |
|
|
* @param request HttpServletRequest which contains docId parameter.
|
80 |
|
|
*/
|
81 |
|
|
public static void clientDeleteRequest(ClientView clientViewBean, ClientViewHelper clientViewHelper) {
|
82 |
|
|
String result = null, docId, subDocId, parentDocId, revisedDocId;
|
83 |
|
|
NodeList nodeLst;
|
84 |
|
|
Node node;
|
85 |
|
|
Document resultSetDoc;
|
86 |
|
|
|
87 |
|
|
docId = clientViewBean.getDocId();
|
88 |
|
|
try {
|
89 |
|
|
//*** First, determine what metadata file is including this file (if any).
|
90 |
|
|
resultSetDoc = clientViewHelper.query(FGDC_DATA_FILE_DOCID_XPATH, docId, null);
|
91 |
|
|
parentDocId = xpath.evaluate("/resultset/document/docid", resultSetDoc.getDocumentElement());
|
92 |
|
|
if (parentDocId != null && !parentDocId.equals("")) {
|
93 |
|
|
clientViewHelper.setMetadataDoc(parentDocId);
|
94 |
|
|
//*** Remove Doc Id from any parent metadata document.
|
95 |
|
|
revisedDocId = removeDataDocIdFromFGDC(docId, parentDocId, clientViewHelper);
|
96 |
|
|
clientViewBean.setDocId(revisedDocId);
|
97 |
3458
|
barteau
|
//*** Set the new Metadata Doc Id in the bean.
|
98 |
|
|
clientViewBean.setMetaFileDocId(revisedDocId);
|
99 |
3321
|
barteau
|
} else {
|
100 |
|
|
clientViewHelper.setMetadataDoc(docId);
|
101 |
|
|
//*** This is a metadata document, so remove all of the sub-docId's.
|
102 |
|
|
nodeLst = (NodeList) xpath.evaluate(SUB_DOCS_PATH, clientViewHelper.getMetadataDoc().getDocumentElement(), XPathConstants.NODESET);
|
103 |
|
|
for(int i = 0; i < nodeLst.getLength(); i++) {
|
104 |
|
|
node = nodeLst.item(i);
|
105 |
|
|
subDocId = node.getNodeValue();
|
106 |
|
|
//*** Remove the sub-document.
|
107 |
|
|
try {
|
108 |
|
|
clientViewHelper.getMetacatClient().delete(subDocId);
|
109 |
|
|
} catch (MetacatException ex) {
|
110 |
|
|
ex.printStackTrace();
|
111 |
|
|
}
|
112 |
|
|
}
|
113 |
3458
|
barteau
|
//*** We're deleting the Meta data doc, so clear it from the bean.
|
114 |
|
|
clientViewBean.setMetaFileDocId(null);
|
115 |
3321
|
barteau
|
}
|
116 |
|
|
//*** Remove the document.
|
117 |
|
|
result = clientViewHelper.getMetacatClient().delete(docId);
|
118 |
|
|
|
119 |
|
|
//*** Save the server feedback in the session, to be used by the view.
|
120 |
|
|
clientViewBean.setMessage(ClientView.DELETE_MESSAGE, result);
|
121 |
|
|
} catch (Exception ex) {
|
122 |
|
|
ex.printStackTrace();
|
123 |
|
|
}
|
124 |
|
|
}
|
125 |
|
|
|
126 |
|
|
private static String removeDataDocIdFromFGDC(String docId, String parentDocId, ClientViewHelper clientViewHelper) throws Exception {
|
127 |
3367
|
barteau
|
String pathToDigform, revision = "", xPathQuery, tmp;
|
128 |
3321
|
barteau
|
Document doc;
|
129 |
|
|
InputStream response;
|
130 |
|
|
Properties prop;
|
131 |
|
|
Node node;
|
132 |
|
|
NodeList nodeLst;
|
133 |
|
|
Reader reader;
|
134 |
|
|
|
135 |
|
|
//*** Get the metadata document and remove the digform branch.
|
136 |
|
|
doc = clientViewHelper.getMetadataDoc();
|
137 |
|
|
if (doc != null) {
|
138 |
3367
|
barteau
|
tmp = PATH4ANCESTOR.replaceFirst("%1s", docId);
|
139 |
|
|
pathToDigform = tmp.replaceFirst("%2s", "digform");
|
140 |
3321
|
barteau
|
node = (Node) xpath.evaluate(pathToDigform, doc.getDocumentElement(), XPathConstants.NODE);
|
141 |
|
|
node.getParentNode().removeChild(node);
|
142 |
3395
|
barteau
|
xPathQuery = XPATH_QUERY_TEMPLATE.replaceFirst("%1s", parentDocId);
|
143 |
3321
|
barteau
|
revision = clientViewHelper.nextVersion(parentDocId, xPathQuery);
|
144 |
|
|
reader = XMLUtilities.getDOMTreeAsReader(doc.getDocumentElement(), false);
|
145 |
|
|
clientViewHelper.getMetacatClient().update(revision, reader, null);
|
146 |
|
|
}
|
147 |
|
|
return(revision);
|
148 |
|
|
}
|
149 |
|
|
|
150 |
3372
|
barteau
|
public static boolean handlePackageUpload(String metaDocId,
|
151 |
|
|
HashMap dataDocIDs,
|
152 |
|
|
String contactName,
|
153 |
|
|
String metaFNm,
|
154 |
3366
|
barteau
|
Document metadataDoc) throws IOException {
|
155 |
3321
|
barteau
|
boolean result = true;
|
156 |
|
|
Node newBranch, metaRootNode;
|
157 |
|
|
|
158 |
|
|
//*** Store the User Name and Doc Id in the FGDC document.
|
159 |
3366
|
barteau
|
newBranch = getFGDCdisinfo(contactName, metaDocId, metaFNm, dataDocIDs);
|
160 |
|
|
//System.out.println("ClientFgdcHelper.handlePackageUpload: " + XMLUtilities.getDOMTreeAsString(newBranch));
|
161 |
3321
|
barteau
|
metaRootNode = addDistInfoToFGDC(newBranch, metadataDoc);
|
162 |
|
|
return(result);
|
163 |
|
|
}
|
164 |
|
|
|
165 |
|
|
|
166 |
|
|
public static boolean isFGDC(Document metadataDoc) {
|
167 |
|
|
boolean result = false;
|
168 |
|
|
DocumentType docType;
|
169 |
|
|
String sysId;
|
170 |
|
|
final String FGDC_TEST_EXPRESSION = "/metadata/idinfo/citation/citeinfo/title";
|
171 |
|
|
Node node = null;
|
172 |
|
|
|
173 |
|
|
//*** First, try the rigid proper way of determining it.
|
174 |
|
|
if (metadataDoc != null) {
|
175 |
|
|
docType = metadataDoc.getDoctype();
|
176 |
|
|
if (docType != null) {
|
177 |
|
|
sysId = docType.getSystemId();
|
178 |
|
|
if (sysId != null)
|
179 |
3540
|
barteau
|
result = (sysId.indexOf(FGDC_SYSTEM_ID) > -1);
|
180 |
3321
|
barteau
|
}
|
181 |
|
|
}
|
182 |
|
|
//*** It might not have a doc type line, so try another method.
|
183 |
|
|
if (metadataDoc != null && !result) {
|
184 |
|
|
try {
|
185 |
|
|
node = (Node) xpath.evaluate(FGDC_TEST_EXPRESSION, metadataDoc.getDocumentElement(), XPathConstants.NODE);
|
186 |
|
|
} catch (XPathExpressionException ex) {
|
187 |
|
|
ex.printStackTrace();
|
188 |
|
|
}
|
189 |
|
|
result = (node != null);
|
190 |
|
|
}
|
191 |
|
|
return(result);
|
192 |
|
|
}
|
193 |
|
|
|
194 |
3366
|
barteau
|
public static boolean hasMetacatInfo(String docId, Document metadataDoc) {
|
195 |
|
|
boolean result = false;
|
196 |
|
|
String queryResult, xPathQuery;
|
197 |
|
|
|
198 |
3372
|
barteau
|
//xPathQuery = String.format(XPATH_QUERY_TEMPLATE, docId);
|
199 |
|
|
xPathQuery = XPATH_QUERY_TEMPLATE.replaceFirst("%1s", docId);
|
200 |
3366
|
barteau
|
try {
|
201 |
|
|
queryResult = xpath.evaluate(xPathQuery, metadataDoc);
|
202 |
|
|
result = (queryResult != null && !queryResult.equals(""));
|
203 |
|
|
} catch (XPathExpressionException ex) {
|
204 |
|
|
ex.printStackTrace();
|
205 |
|
|
}
|
206 |
|
|
return(result);
|
207 |
|
|
}
|
208 |
|
|
|
209 |
|
|
private static Node getFGDCdisinfo(String contactName, String resourceDescription, String metaFNm, HashMap dataDocIDs) throws IOException {
|
210 |
|
|
Node result = null, node, digformBranch, formname, stdorder, formcont;
|
211 |
3321
|
barteau
|
Document doc;
|
212 |
|
|
Iterator iterIt;
|
213 |
3366
|
barteau
|
String key, value, fileInfo[];
|
214 |
3321
|
barteau
|
|
215 |
|
|
//*** This is a valid/minimal FGDC "distinfo" branch.
|
216 |
|
|
final String XML = "<distinfo>"
|
217 |
|
|
+ " <distrib>"
|
218 |
|
|
+ " <cntinfo>"
|
219 |
|
|
+ " <cntperp>"
|
220 |
|
|
+ " <cntper></cntper>"
|
221 |
|
|
+ " </cntperp>"
|
222 |
|
|
+ " <cntaddr>"
|
223 |
|
|
+ " <addrtype></addrtype>"
|
224 |
|
|
+ " <address></address>"
|
225 |
|
|
+ " <city></city>"
|
226 |
|
|
+ " <state></state>"
|
227 |
|
|
+ " <postal></postal>"
|
228 |
|
|
+ " <country></country>"
|
229 |
|
|
+ " </cntaddr>"
|
230 |
|
|
+ " <cntvoice></cntvoice>"
|
231 |
|
|
+ " </cntinfo>"
|
232 |
|
|
+ " </distrib>"
|
233 |
|
|
+ " <resdesc></resdesc>"
|
234 |
|
|
+ " <distliab></distliab>"
|
235 |
|
|
+ " <stdorder>"
|
236 |
|
|
+ " <digform>"
|
237 |
|
|
+ " <digtinfo>"
|
238 |
|
|
+ " <formname></formname>"
|
239 |
3366
|
barteau
|
+ " <formcont></formcont>"
|
240 |
3321
|
barteau
|
+ " </digtinfo>"
|
241 |
|
|
+ " <digtopt>"
|
242 |
|
|
+ " <onlinopt>"
|
243 |
|
|
+ " <computer>"
|
244 |
|
|
+ " <networka>"
|
245 |
|
|
+ " <networkr></networkr>"
|
246 |
|
|
+ " </networka>"
|
247 |
|
|
+ " </computer>"
|
248 |
|
|
+ " </onlinopt>"
|
249 |
|
|
+ " </digtopt>"
|
250 |
|
|
+ " </digform>"
|
251 |
|
|
+ " <fees></fees>"
|
252 |
|
|
+ " </stdorder>"
|
253 |
3366
|
barteau
|
+ " <custom></custom>"
|
254 |
3321
|
barteau
|
+ "</distinfo>";
|
255 |
|
|
|
256 |
|
|
doc = XMLUtilities.getXMLReaderAsDOMDocument(new StringReader(XML));
|
257 |
|
|
result = doc.getDocumentElement();
|
258 |
|
|
try {
|
259 |
|
|
//*** Set the Contact Person.
|
260 |
|
|
node = (Node) xpath.evaluate("/distinfo/distrib/cntinfo/cntperp/cntper", result, XPathConstants.NODE);
|
261 |
3540
|
barteau
|
ClientViewHelper.setTextContent(xpath, node, contactName);
|
262 |
|
|
//node.setTextContent(contactName); Not in java 1.4
|
263 |
|
|
|
264 |
3321
|
barteau
|
//*** Set the metadata Doc Id.
|
265 |
|
|
node = (Node) xpath.evaluate("/distinfo/resdesc", result, XPathConstants.NODE);
|
266 |
3540
|
barteau
|
ClientViewHelper.setTextContent(xpath, node, resourceDescription);
|
267 |
|
|
//node.setTextContent(resourceDescription); Not in java 1.4
|
268 |
|
|
|
269 |
3366
|
barteau
|
//*** Set the metadata filename.
|
270 |
|
|
node = (Node) xpath.evaluate("/distinfo/custom", result, XPathConstants.NODE);
|
271 |
3540
|
barteau
|
ClientViewHelper.setTextContent(xpath, node, metaFNm);
|
272 |
|
|
//node.setTextContent(metaFNm); Not in java 1.4
|
273 |
3321
|
barteau
|
|
274 |
|
|
//*** Loop thru the files, setting their format and Doc Id.
|
275 |
|
|
stdorder = (Node) xpath.evaluate("/distinfo/stdorder", result, XPathConstants.NODE);
|
276 |
|
|
digformBranch = (Node) xpath.evaluate("/distinfo/stdorder/digform", result, XPathConstants.NODE);
|
277 |
|
|
iterIt = dataDocIDs.keySet().iterator();
|
278 |
|
|
while(iterIt.hasNext()) {
|
279 |
|
|
//*** Save the data file Doc ID (required).
|
280 |
|
|
key = (String) iterIt.next();
|
281 |
|
|
node = (Node) xpath.evaluate("digtopt/onlinopt/computer/networka/networkr", digformBranch, XPathConstants.NODE);
|
282 |
3540
|
barteau
|
ClientViewHelper.setTextContent(xpath, node, key);
|
283 |
|
|
//node.setTextContent(key);
|
284 |
3366
|
barteau
|
|
285 |
|
|
fileInfo = (String[]) dataDocIDs.get(key);
|
286 |
|
|
if (fileInfo != null) {
|
287 |
|
|
//*** Save the data file format (optional).
|
288 |
|
|
formname = (Node) xpath.evaluate("digtinfo/formname", digformBranch, XPathConstants.NODE);
|
289 |
|
|
if ((value = fileInfo[ClientView.FORMAT_TYPE]) != null && !value.equals("")) {
|
290 |
3540
|
barteau
|
ClientViewHelper.setTextContent(xpath, formname, value);
|
291 |
|
|
//formname.setTextContent(value);
|
292 |
3366
|
barteau
|
} else {
|
293 |
|
|
//*** We did a deep clone of the branch, so clear prior contents.
|
294 |
3540
|
barteau
|
ClientViewHelper.setTextContent(xpath, formname, "");
|
295 |
|
|
//formname.setTextContent("");
|
296 |
3366
|
barteau
|
}
|
297 |
|
|
//*** Save the data file name.
|
298 |
|
|
formcont = (Node) xpath.evaluate("digtinfo/formcont", digformBranch, XPathConstants.NODE);
|
299 |
|
|
if ((value = fileInfo[ClientView.FILE_NAME]) != null && !value.equals("")) {
|
300 |
3540
|
barteau
|
ClientViewHelper.setTextContent(xpath, formcont, value);
|
301 |
|
|
//formcont.setTextContent(value);
|
302 |
3366
|
barteau
|
} else {
|
303 |
|
|
//*** We did a deep clone of the branch, so clear prior contents.
|
304 |
3540
|
barteau
|
ClientViewHelper.setTextContent(xpath, formcont, "");
|
305 |
|
|
//formcont.setTextContent("");
|
306 |
3366
|
barteau
|
}
|
307 |
3321
|
barteau
|
}
|
308 |
|
|
//*** Clone branch for next file.
|
309 |
|
|
if (iterIt.hasNext()) {
|
310 |
|
|
digformBranch = digformBranch.cloneNode(true);
|
311 |
|
|
stdorder.appendChild(digformBranch);
|
312 |
|
|
}
|
313 |
|
|
}
|
314 |
|
|
} catch (XPathExpressionException ex) {
|
315 |
|
|
ex.printStackTrace();
|
316 |
|
|
}
|
317 |
|
|
return(result);
|
318 |
|
|
}
|
319 |
|
|
|
320 |
|
|
private static Node addDistInfoToFGDC(Node newBranch, Document metadataDoc) {
|
321 |
|
|
Node result = null, node;
|
322 |
|
|
|
323 |
|
|
if (newBranch != null) {
|
324 |
|
|
result = metadataDoc.getDocumentElement();
|
325 |
|
|
try {
|
326 |
|
|
//*** Get a reference to the FGDC required "metainfo" node (only 1 allowed).
|
327 |
|
|
node = (Node) xpath.evaluate("/metadata/metainfo", result, XPathConstants.NODE);
|
328 |
|
|
if (node != null) {
|
329 |
|
|
newBranch = metadataDoc.importNode(newBranch, true);
|
330 |
|
|
//*** Add the new "distinfo" before it.
|
331 |
|
|
result.insertBefore(newBranch, node);
|
332 |
|
|
}
|
333 |
|
|
} catch (XPathExpressionException ex) {
|
334 |
|
|
ex.printStackTrace();
|
335 |
|
|
}
|
336 |
|
|
}
|
337 |
|
|
return(result);
|
338 |
|
|
}
|
339 |
3372
|
barteau
|
|
340 |
|
|
public static void updateFileNameAndType(Node root, String dataDocId, String[] fileInfo) {
|
341 |
|
|
Node digform;
|
342 |
|
|
String tmp, pathToDigform;
|
343 |
|
|
final String FORMNAME_PATH = "digtinfo/formname"; //*** File format type.
|
344 |
|
|
final String FORMCONT_PATH = "digtinfo/formcont"; //*** Original file name.
|
345 |
|
|
|
346 |
|
|
tmp = PATH4ANCESTOR.replaceFirst("%1s", dataDocId);
|
347 |
|
|
pathToDigform = tmp.replaceFirst("%2s", "digform");
|
348 |
|
|
digform = ClientViewHelper.getNode(xpath, pathToDigform, root);
|
349 |
|
|
if (digform != null) {
|
350 |
|
|
ClientViewHelper.updateNodeText(digform, xpath, FORMNAME_PATH, fileInfo[ClientView.FORMAT_TYPE]);
|
351 |
|
|
ClientViewHelper.updateNodeText(digform, xpath, FORMCONT_PATH, fileInfo[ClientView.FILE_NAME]);
|
352 |
|
|
}
|
353 |
|
|
}
|
354 |
|
|
|
355 |
|
|
public static void updateMetadataFileName(Node root, String metadataDocId, String fileName) {
|
356 |
|
|
String pathToResdesc;
|
357 |
|
|
Node resdesc;
|
358 |
|
|
|
359 |
|
|
if (fileName != null && !fileName.equals("")) {
|
360 |
|
|
pathToResdesc = XPATH_QUERY_TEMPLATE.replaceFirst("%1s", metadataDocId);
|
361 |
4168
|
leinfelder
|
ClientViewHelper.updateNodeText(root, xpath, pathToResdesc, metadataDocId);
|
362 |
3372
|
barteau
|
}
|
363 |
|
|
}
|
364 |
3321
|
barteau
|
}
|