source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/DocumentMaker.java

Last change on this file was 37177, checked in by davidb, 16 months ago

Introduction of new optional parameter docVersion. If null (or equal to the empty string), then code works as before. Designed to work with the file-level document-version history mechanism, if non-empty, then this value is used to change where doc.xml on the file system is read from

  • Property svn:executable set to *
File size: 19.0 KB
Line 
1/*
2 * DocumentMaker.java
3 * The Document Maker service that can be used to create/modify custom
4 * documents in Greenstone collection
5 *
6 * Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22package org.greenstone.gsdl3.service;
23
24import java.io.BufferedReader;
25import java.io.InputStreamReader;
26import java.io.OutputStream;
27import java.io.Serializable;
28import java.lang.reflect.Type;
29import java.util.ArrayList;
30import java.util.HashMap;
31import java.util.Iterator;
32import java.util.List;
33import java.util.Map;
34import java.util.Set;
35
36import org.apache.log4j.*;
37
38import org.greenstone.gsdl3.util.UserContext;
39import org.greenstone.gsdl3.util.SimpleCollectionDatabase;
40
41
42import org.greenstone.gsdl3.util.GSDocumentModel;
43import org.greenstone.gsdl3.util.GSFile;
44import org.greenstone.gsdl3.util.GSPath;
45import org.greenstone.gsdl3.util.GSXML;
46import org.greenstone.gsdl3.util.OID;
47import org.greenstone.gsdl3.util.UserContext;
48import org.greenstone.gsdl3.util.XMLConverter;
49
50import org.w3c.dom.Document;
51import org.w3c.dom.Element;
52import org.w3c.dom.NodeList;
53
54import com.google.gson.Gson;
55import com.google.gson.reflect.TypeToken;
56
57public class DocumentMaker extends ServiceRack
58{
59 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.ArchiveIO.class.getName());
60
61 GSDocumentModel _GSDM = null;
62
63 /****************************************************
64 * The list of services the Document Maker supports *
65 ***************************************************/
66 //Document/section services
67 protected static final String DOCUMENT_CREATE = "DocumentCreate";
68 protected static final String DOCUMENT_DELETE = "DocumentDelete";
69 protected static final String DOCUMENT_DUPLICATE = "DocumentDuplicate";
70 protected static final String DOCUMENT_MOVE = "DocumentMove";
71 protected static final String DOCUMENT_MERGE = "DocumentMerge";
72 protected static final String DOCUMENT_SPLIT = "DocumentSplit";
73 protected static final String DOCUMENT_GET_INFORMATION = "DocumentGetInformation";
74
75 //Other services
76 protected static final String DOCUMENT_EXECUTE_TRANSACTION = "DocumentExecuteTransaction";
77 /***************************************************/
78
79 String[] services = { DOCUMENT_CREATE, DOCUMENT_DELETE, DOCUMENT_DUPLICATE, DOCUMENT_GET_INFORMATION, DOCUMENT_MOVE, DOCUMENT_MERGE, DOCUMENT_SPLIT, DOCUMENT_EXECUTE_TRANSACTION };
80
81 /** configure this service */
82 public boolean configure(Element info, Element extra_info)
83 {
84 if (!super.configure(info, extra_info))
85 {
86 return false;
87 }
88
89 logger.info("Configuring DocumentMaker...");
90 this.config_info = info;
91
92 for (int i = 0; i < services.length; i++)
93 {
94 Element service = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
95 service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
96 service.setAttribute(GSXML.NAME_ATT, services[i]);
97 this.short_service_info.appendChild(service);
98 }
99
100 _GSDM = new GSDocumentModel(this.site_home, this.router);
101
102 return true;
103 }
104
105 protected Element getServiceDescription(Document doc, String service_id, String lang, String subset)
106 {
107 for (int i = 0; i < services.length; i++)
108 {
109 if (service_id.equals(services[i]))
110 {
111 Element service_elem = doc.createElement(GSXML.SERVICE_ELEM);
112 service_elem.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
113 service_elem.setAttribute(GSXML.NAME_ATT, services[i]);
114 return service_elem;
115 }
116 }
117
118 return null;
119 }
120
121 /************
122 * Services *
123 ***********/
124
125 protected Element processDocumentCreate(Element request)
126 {
127 Document result_doc = XMLConverter.newDOM();
128 Element result = GSXML.createBasicResponse(result_doc, DOCUMENT_CREATE);
129
130 if (request == null)
131 {
132 GSXML.addError(result, DOCUMENT_CREATE + ": Request is null", GSXML.ERROR_TYPE_SYNTAX);
133 return result;
134 }
135
136 UserContext userContext = new UserContext(request);
137
138 //Get the list of documents to create
139 NodeList documents = request.getElementsByTagName(GSXML.DOCUMENT_ELEM);
140 for (int i = 0; i < documents.getLength(); i++)
141 {
142 //Get information about the current new document
143 Element currentDoc = (Element) documents.item(i);
144 String oid = currentDoc.getAttribute(GSXML.NODE_ID_ATT);
145 String optDocVersion = currentDoc.getAttribute(GSXML.DOC_VERSION_ATT);
146 String collection = currentDoc.getAttribute(GSXML.COLLECTION_ATT);
147
148 _GSDM.documentCreate(oid, optDocVersion, collection, userContext);
149 if (_GSDM.checkError(result, DOCUMENT_CREATE))
150 {
151 return result;
152 }
153 }
154
155 return result;
156 }
157
158 protected Element processDocumentDelete(Element request)
159 {
160 Document result_doc = XMLConverter.newDOM();
161 Element result = GSXML.createBasicResponse(result_doc, DOCUMENT_DELETE);
162
163 if (request == null)
164 {
165 GSXML.addError(result, DOCUMENT_DELETE + ": Request is null", GSXML.ERROR_TYPE_SYNTAX);
166 return result;
167 }
168
169 UserContext userContext = new UserContext(request);
170
171 //Get the list of documents to delete
172 NodeList documents = request.getElementsByTagName(GSXML.DOCUMENT_ELEM);
173 for (int i = 0; i < documents.getLength(); i++)
174 {
175 Element currentDoc = (Element) documents.item(i);
176 String oid = currentDoc.getAttribute(GSXML.NODE_ID_ATT);
177 String optDocVersion = currentDoc.getAttribute(GSXML.DOC_VERSION_ATT);
178 String collection = currentDoc.getAttribute(GSXML.COLLECTION_ATT);
179
180 _GSDM.documentDelete(oid, optDocVersion, collection, userContext);
181 if (_GSDM.checkError(result, DOCUMENT_DELETE))
182 {
183 return result;
184 }
185 }
186
187 return result;
188 }
189
190 protected Element processDocumentDuplicate(Element request)
191 {
192 Document result_doc = XMLConverter.newDOM();
193 Element result = GSXML.createBasicResponse(result_doc, DOCUMENT_DUPLICATE);
194
195 if (request == null)
196 {
197 GSXML.addError(result, DOCUMENT_DUPLICATE + ": Request is null", GSXML.ERROR_TYPE_SYNTAX);
198 return result;
199 }
200
201 UserContext userContext = new UserContext(request);
202
203 //Get the list of documents to duplicate
204 NodeList documents = request.getElementsByTagName(GSXML.DOCUMENT_ELEM);
205 for (int i = 0; i < documents.getLength(); i++)
206 {
207 Element currentDoc = (Element) documents.item(i);
208 String oid = currentDoc.getAttribute(GSXML.NODE_ID_ATT);
209 String optDocVersion = currentDoc.getAttribute(GSXML.DOC_VERSION_ATT);
210 String collection = currentDoc.getAttribute(GSXML.COLLECTION_ATT);
211 String newOID = currentDoc.getAttribute("new" + GSXML.NODE_ID_ATT);
212 String optNewDocVersion = currentDoc.getAttribute("new" + GSXML.DOC_VERSION_ATT);
213 String newCollection = currentDoc.getAttribute("new" + GSXML.COLLECTION_ATT);
214 String operation = currentDoc.getAttribute("operation");
215
216 _GSDM.documentMoveOrDuplicate(oid, optDocVersion, collection,
217 newOID, optNewDocVersion, newCollection,
218 _GSDM.operationStringToInt(operation), false, userContext);
219 if (_GSDM.checkError(result, DOCUMENT_DUPLICATE))
220 {
221 return result;
222 }
223 }
224
225 return result;
226 }
227
228 protected Element processDocumentGetInformation(Element request)
229 {
230 Document result_doc = XMLConverter.newDOM();
231 Element result = GSXML.createBasicResponse(result_doc, DOCUMENT_GET_INFORMATION);
232
233 if (request == null)
234 {
235 GSXML.addError(result, DOCUMENT_GET_INFORMATION + ": Request is null", GSXML.ERROR_TYPE_SYNTAX);
236 return result;
237 }
238
239 UserContext userContext = new UserContext(request);
240
241 //Get the list of documents to duplicate
242 NodeList documents = request.getElementsByTagName(GSXML.DOCUMENT_ELEM);
243 for (int i = 0; i < documents.getLength(); i++)
244 {
245 Element currentDoc = (Element) documents.item(i);
246 String oid = currentDoc.getAttribute(GSXML.NODE_ID_ATT);
247 String optDocVersion = currentDoc.getAttribute(GSXML.DOC_VERSION_ATT);
248 String collection = currentDoc.getAttribute(GSXML.COLLECTION_ATT);
249
250 NodeList requestedInfoList = currentDoc.getElementsByTagName("info"); //TODO: Replace info with a constant
251 String[] requestedInfo = new String[requestedInfoList.getLength()];
252
253 for (int j = 0; j < requestedInfoList.getLength(); j++)
254 {
255 requestedInfo[j] = ((Element) requestedInfoList.item(j)).getAttribute(GSXML.NAME_ATT);
256 }
257
258 _GSDM.documentGetInformation(oid, optDocVersion, collection, requestedInfo, userContext);
259 if (_GSDM.checkError(result, DOCUMENT_GET_INFORMATION))
260 {
261 return result;
262 }
263 }
264
265 return result;
266 }
267
268 protected Element processDocumentMove(Element request)
269 {
270 Document result_doc = XMLConverter.newDOM();
271 Element result = GSXML.createBasicResponse(result_doc, DOCUMENT_MOVE);
272
273 if (request == null)
274 {
275 GSXML.addError(result, DOCUMENT_MOVE + ": Request is null", GSXML.ERROR_TYPE_SYNTAX);
276 return result;
277 }
278
279 UserContext userContext = new UserContext(request);
280
281 //Get the list of documents to duplicate
282 NodeList documents = request.getElementsByTagName(GSXML.DOCUMENT_ELEM);
283 for (int i = 0; i < documents.getLength(); i++)
284 {
285 Element currentDoc = (Element) documents.item(i);
286 String oid = currentDoc.getAttribute(GSXML.NODE_ID_ATT);
287 String optDocVersion = currentDoc.getAttribute(GSXML.DOC_VERSION_ATT);
288 String collection = currentDoc.getAttribute(GSXML.COLLECTION_ATT);
289 String newOID = currentDoc.getAttribute("new" + GSXML.NODE_ID_ATT);
290 String optNewDocVersion = currentDoc.getAttribute("new" + GSXML.DOC_VERSION_ATT);
291 String newCollection = currentDoc.getAttribute("new" + GSXML.COLLECTION_ATT);
292 String operation = currentDoc.getAttribute("operation");
293
294 _GSDM.documentMoveOrDuplicate(oid, optDocVersion, collection,
295 newOID, optNewDocVersion, newCollection,
296 _GSDM.operationStringToInt(operation), true, userContext);
297 if (_GSDM.checkError(result, DOCUMENT_MOVE))
298 {
299 return result;
300 }
301 }
302 return result;
303 }
304
305 protected Element processDocumentMerge(Element request)
306 {
307 Document result_doc = XMLConverter.newDOM();
308 Element result = GSXML.createBasicResponse(result_doc, DOCUMENT_MERGE);
309
310 if (request == null)
311 {
312 GSXML.addError(result, DOCUMENT_MERGE + ": Request is null", GSXML.ERROR_TYPE_SYNTAX);
313 return result;
314 }
315
316 UserContext userContext = new UserContext(request);
317
318 //Get the list of documents to duplicate
319 NodeList documents = request.getElementsByTagName(GSXML.DOCUMENT_ELEM);
320 for (int i = 0; i < documents.getLength(); i++)
321 {
322 Element currentDoc = (Element) documents.item(i);
323 String oid = currentDoc.getAttribute(GSXML.NODE_ID_ATT);
324 String collection = currentDoc.getAttribute(GSXML.COLLECTION_ATT);
325 String optDocVersion = currentDoc.getAttribute(GSXML.DOC_VERSION_ATT);
326 String mergeOID = currentDoc.getAttribute("merge" + GSXML.NODE_ID_ATT);
327
328 _GSDM.documentMerge(oid, optDocVersion, collection, mergeOID, userContext);
329 if (_GSDM.checkError(result, DOCUMENT_MERGE))
330 {
331 return result;
332 }
333 }
334
335 return result;
336 }
337
338 protected Element processDocumentSplit(Element request)
339 {
340 Document result_doc = XMLConverter.newDOM();
341 Element result = GSXML.createBasicResponse(result_doc, DOCUMENT_SPLIT);
342
343 if (request == null)
344 {
345 GSXML.addError(result, DOCUMENT_SPLIT + ": Request is null", GSXML.ERROR_TYPE_SYNTAX);
346 return result;
347 }
348
349 UserContext userContext = new UserContext(request);
350
351 //Get the list of documents to duplicate
352 NodeList documents = request.getElementsByTagName(GSXML.DOCUMENT_ELEM);
353 for (int i = 0; i < documents.getLength(); i++)
354 {
355 Element currentDoc = (Element) documents.item(i);
356 String oid = currentDoc.getAttribute(GSXML.NODE_ID_ATT);
357 String optDocVersion = currentDoc.getAttribute(GSXML.DOC_VERSION_ATT);
358 String collection = currentDoc.getAttribute(GSXML.COLLECTION_ATT);
359 String splitPoint = currentDoc.getAttribute("splitpoint");
360
361 int split;
362 try
363 {
364 split = Integer.parseInt(splitPoint);
365 }
366 catch (Exception ex)
367 {
368 GSXML.addError(result, DOCUMENT_SPLIT + ": The split point was not an integer", GSXML.ERROR_TYPE_SYNTAX);
369 return result;
370 }
371
372 _GSDM.documentSplit(oid, optDocVersion, collection, split, userContext);
373 if (_GSDM.checkError(result, DOCUMENT_SPLIT))
374 {
375 return result;
376 }
377 }
378
379 return result;
380 }
381
382 protected Element processDocumentExecuteTransaction(Element request)
383 {
384 Document result_doc = XMLConverter.newDOM();
385 Element result = GSXML.createBasicResponse(result_doc, DOCUMENT_EXECUTE_TRANSACTION);
386
387 if (request == null)
388 {
389 GSXML.addError(result, DOCUMENT_EXECUTE_TRANSACTION + ": Request is null", GSXML.ERROR_TYPE_SYNTAX);
390 return result;
391 }
392
393 UserContext userContext = new UserContext(request);
394
395 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
396 if (param_list == null)
397 {
398 GSXML.addError(result, DOCUMENT_EXECUTE_TRANSACTION + ": Request has no parameter list", GSXML.ERROR_TYPE_SYNTAX);
399 return result;
400 }
401
402 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
403 String transactionString = (String) params.get("transactions");
404 transactionString = transactionString.replace("%26", "&");
405
406 List<Map<String, String>> transactions = null;
407 try
408 {
409 Gson gson = new Gson();
410 Type type = new TypeToken<List<Map<String, String>>>()
411 {
412 }.getType();
413 transactions = gson.fromJson(transactionString, type);
414 }
415 catch (Exception ex)
416 {
417 ex.printStackTrace();
418 }
419
420 if (transactions != null && transactions.size() > 0)
421 {
422 for (int j = 0; j < transactions.size(); j++)
423 {
424 Map keyValueMap = transactions.get(j);
425 String operation = (String) keyValueMap.get("operation");
426 if (operation.equals("move") || operation.equals("duplicate"))
427 {
428 String origOID = (String) keyValueMap.get("oid");
429 String optOrigDocVersion = (String) keyValueMap.get("optDocVersion");
430 String origCollection = (String) keyValueMap.get("collection");
431 String newOID = (String) keyValueMap.get("newOID");
432 String optNewDocVersion = (String) keyValueMap.get("optNewDocVersion");
433 String newCollection = (String) keyValueMap.get("newCollection");
434 String subOperation = (String) keyValueMap.get("subOperation");
435
436 _GSDM.documentMoveOrDuplicate(origOID, optOrigDocVersion, origCollection,
437 newOID, optNewDocVersion, newCollection,
438 _GSDM.operationStringToInt(subOperation), operation.equals("move"), userContext);
439 }
440 else if (operation.equals("createDocument"))
441 {
442 String oid = (String) keyValueMap.get("oid");
443 String optDocVersion = (String) keyValueMap.get("optDocVersion");
444 String collection = (String) keyValueMap.get("collection");
445
446 _GSDM.documentCreate(oid, optDocVersion, collection, userContext);
447 }
448 else if (operation.equals("create"))
449 {
450 String oid = (String) keyValueMap.get("oid");
451 String optDocVersion = (String) keyValueMap.get("optDocVersion");
452 String collection = (String) keyValueMap.get("collection");
453 String subOperation = (String) keyValueMap.get("subOperation");
454
455 //_GSDM.documentCreate(oid, optDocVersion, collection, userContext); <--- Maybe go back to this
456 _GSDM.documentXMLSetSection(oid, optDocVersion, collection, result_doc.createElement(GSXML.DOCXML_SECTION_ELEM), _GSDM.operationStringToInt(subOperation), userContext);
457 }
458 else if (operation.equals("delete"))
459 {
460 String oid = (String) keyValueMap.get("oid");
461 String optDocVersion = (String) keyValueMap.get("optDocVersion");
462 String collection = (String) keyValueMap.get("collection");
463
464 _GSDM.documentDelete(oid, optDocVersion, collection, userContext);
465 }
466 else if (operation.equals("setText"))
467 {
468 String oid = (String) keyValueMap.get("oid");
469 String optDocVersion = (String) keyValueMap.get("optDocVersion");
470 String collection = (String) keyValueMap.get("collection");
471 String newContent = (String) keyValueMap.get("text");
472
473 _GSDM.documentXMLSetText(oid, optDocVersion, collection, newContent, userContext);
474 // make sure NoText metadata is not set (in case we have added text where there was none before)
475 _GSDM.documentXMLDeleteMetadata(oid, optDocVersion, collection, "NoText", userContext);
476 // only top level doc ids are in database
477 markDocumentInFlatDatabase("R", collection, OID.getTop(oid));
478
479 }
480
481 if (_GSDM.checkError(result, DOCUMENT_EXECUTE_TRANSACTION))
482 {
483 return result;
484 }
485 }
486 }
487 return result;
488
489 }
490 protected void markDocumentInFlatDatabase(String mark, String collection, String oid) {
491
492 Document msg_doc = XMLConverter.newDOM();
493 Element message = msg_doc.createElement(GSXML.MESSAGE_ELEM);
494 UserContext userContext = new UserContext();
495 Element query_request = GSXML.createBasicRequest(msg_doc, GSXML.REQUEST_TYPE_DESCRIBE , collection, userContext);
496 message.appendChild(query_request);
497 Element result = (Element) this.router.process(message);
498 Element resp_elem = (Element) GSXML.getChildByTagName(result, GSXML.RESPONSE_ELEM);
499 Element coll_elem = (Element) GSXML.getChildByTagName(resp_elem, GSXML.COLLECTION_ELEM);
500 String dbtype = coll_elem.getAttribute(GSXML.DB_TYPE_ATT);
501
502 SimpleCollectionDatabase coll_db = new SimpleCollectionDatabase(dbtype);
503 if (!coll_db.databaseOK())
504 {
505 logger.error("Couldn't create the collection database of type " + dbtype);
506 return;
507 }
508
509 // Open database for reading
510 String coll_db_file = GSFile.archivesDatabaseFile(this.site_home, collection, dbtype);
511 if (!coll_db.openDatabase(coll_db_file, SimpleCollectionDatabase.READ))
512 {
513 logger.error("Could not open collection archives database. Database doesn't exist or else somebody's already using it?");
514 return;
515 }
516 String old_value = coll_db.getValue(oid);
517 String new_value = old_value.replace("<index-status>B", "<index-status>" + mark);
518 // Close database for reading
519 coll_db.closeDatabase();
520 if (!coll_db.openDatabase(coll_db_file, SimpleCollectionDatabase.WRITE))
521 {
522 logger.error("Could not open collection archives database. Somebody already using this database!");
523 return;
524 }
525 coll_db.setValue(oid, new_value);
526 coll_db.closeDatabase();
527
528 }
529}
Note: See TracBrowser for help on using the repository browser.