001 /*
002 * $Revision: 15621 $ $Date: 2009-07-25 08:32:01 +0200 (Sat, 25 Jul 2009) $ This file is part of M y C o R e See http://www.mycore.de/ for details. This program
003 * is free software; you can use it, redistribute it and / or modify it under the terms of the GNU General Public License (GPL) as published by the Free
004 * Software Foundation; either version 2 of the License or (at your option) any later version. This program is distributed in the hope that it will be useful,
005 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
006 * more details. You should have received a copy of the GNU General Public License along with this program, in a file called gpl.txt or license.txt. If not,
007 * write to the Free Software Foundation Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
008 */
009
010 package org.mycore.frontend.cli;
011
012 import java.io.File;
013 import java.io.FileNotFoundException;
014 import java.io.FileOutputStream;
015 import java.io.IOException;
016 import java.io.InputStream;
017 import java.util.ArrayList;
018 import java.util.Collections;
019 import java.util.Hashtable;
020 import java.util.List;
021
022 import javax.xml.transform.Transformer;
023 import javax.xml.transform.TransformerConfigurationException;
024 import javax.xml.transform.TransformerException;
025 import javax.xml.transform.TransformerFactory;
026 import javax.xml.transform.TransformerFactoryConfigurationError;
027 import javax.xml.transform.stream.StreamResult;
028 import javax.xml.transform.stream.StreamSource;
029
030 import org.apache.log4j.Logger;
031
032 import org.mycore.common.MCRException;
033 import org.mycore.common.MCRSessionMgr;
034 import org.mycore.common.xml.MCRURIResolver;
035 import org.mycore.common.xml.MCRXMLHelper;
036 import org.mycore.datamodel.common.MCRActiveLinkException;
037 import org.mycore.datamodel.metadata.MCRObject;
038 import org.mycore.datamodel.metadata.MCRObjectID;
039 import org.mycore.datamodel.common.MCRXMLTableManager;
040
041 import org.mycore.parsers.bool.MCRCondition;
042 import org.mycore.services.fieldquery.MCRFieldDef;
043 import org.mycore.services.fieldquery.MCRFieldValue;
044 import org.mycore.services.fieldquery.MCRQuery;
045 import org.mycore.services.fieldquery.MCRQueryManager;
046 import org.mycore.services.fieldquery.MCRQueryParser;
047 import org.mycore.services.fieldquery.MCRHit;
048 import org.mycore.services.fieldquery.MCRResults;
049 import org.mycore.services.fieldquery.MCRSearcher;
050 import org.mycore.services.fieldquery.MCRSearcherFactory;
051
052 /**
053 * Provides static methods that implement commands for the MyCoRe command line interface.
054 *
055 * @author Jens Kupferschmidt
056 * @author Frank Luetzenkirchen
057 * @version $Revision: 15621 $ $Date: 2009-07-25 08:32:01 +0200 (Sat, 25 Jul 2009) $
058 */
059 public class MCRObjectCommands extends MCRAbstractCommands {
060 /** The logger */
061 private static Logger LOGGER = Logger.getLogger(MCRObjectCommands.class.getName());
062
063 /** Default transformer script */
064 public static final String DEFAULT_TRANSFORMER = "save-object.xsl";
065
066 /** static compiled transformer stylesheets */
067 private static Hashtable<String, javax.xml.transform.Transformer> translist = new Hashtable<String, javax.xml.transform.Transformer>();
068
069 /**
070 * The empty constructor.
071 */
072 public MCRObjectCommands() {
073 super();
074
075 MCRCommand com = null;
076
077 com = new MCRCommand("delete all objects of type {0}", "org.mycore.frontend.cli.MCRObjectCommands.deleteAllObjects String",
078 "Removes MCRObjects in the number range between the MCRObjectID {0} and {1}.");
079 command.add(com);
080
081 com = new MCRCommand("delete object from {0} to {1}", "org.mycore.frontend.cli.MCRObjectCommands.deleteFromTo String String",
082 "Removes MCRObjects in the number range between the MCRObjectID {0} and {1}.");
083 command.add(com);
084
085 com = new MCRCommand("delete object {0}", "org.mycore.frontend.cli.MCRObjectCommands.delete String",
086 "Removes a MCRObject with the MCRObjectID {0}");
087 command.add(com);
088
089 com = new MCRCommand("load object from file {0}", "org.mycore.frontend.cli.MCRObjectCommands.loadFromFile String",
090 "Adds a MCRObject form the file {0} to the system.");
091 command.add(com);
092
093 com = new MCRCommand("load all objects from directory {0}", "org.mycore.frontend.cli.MCRObjectCommands.loadFromDirectory String",
094 "Loads all MCRObjects form the directory {0} to the system.");
095 command.add(com);
096
097 com = new MCRCommand("update object from file {0}", "org.mycore.frontend.cli.MCRObjectCommands.updateFromFile String",
098 "Updates a MCRObject form the file {0} in the system.");
099 command.add(com);
100
101 com = new MCRCommand("update all objects from directory {0}",
102 "org.mycore.frontend.cli.MCRObjectCommands.updateFromDirectory String",
103 "Updates all MCRObjects form the directory {0} in the system.");
104 command.add(com);
105
106 com = new MCRCommand(
107 "export object from {0} to {1} to directory {2} with {3}",
108 "org.mycore.frontend.cli.MCRObjectCommands.export String String String String",
109 "Stores all MCRObjects with MCRObjectID's between {0} and {1} to the directory {2} with the stylesheet {3}-object.xsl. For {3} save is the default.");
110 command.add(com);
111
112 com = new MCRCommand("export object {0} to directory {1} with {2}",
113 "org.mycore.frontend.cli.MCRObjectCommands.export String String String",
114 "Stores the MCRObject with the MCRObjectID {0} to the directory {1} with the stylesheet {2}-object.xsl. For {2} save is the default.");
115 command.add(com);
116
117 com = new MCRCommand("export all objects of type {0} to directory {1} with {2}",
118 "org.mycore.frontend.cli.MCRObjectCommands.exportAllObjects String String String",
119 "Stores all MCRObjects of type {0} to directory {1} with the stylesheet mcr_{2}-object.xsl. For {2} save is the default.");
120 command.add(com);
121
122 com = new MCRCommand("get last ID for base {0}", "org.mycore.frontend.cli.MCRObjectCommands.getLastID String",
123 "Returns the last used MCRObjectID for the ID base {0}.");
124 command.add(com);
125
126 com = new MCRCommand("get next ID for base {0}", "org.mycore.frontend.cli.MCRObjectCommands.getNextID String",
127 "Returns the next free MCRObjectID for the ID base {0}.");
128 command.add(com);
129
130 com = new MCRCommand("check file {0}", "org.mycore.frontend.cli.MCRObjectCommands.checkXMLFile String",
131 "Checks the data file {0} against the XML Schema.");
132 command.add(com);
133
134 com = new MCRCommand("repair metadata search of type {0}", "org.mycore.frontend.cli.MCRObjectCommands.repairMetadataSearch String",
135 "Reads the SQL store table of MCRObject XML files for the type {0} and restore them to the search store.");
136 command.add(com);
137
138 com = new MCRCommand("repair metadata search of ID {0}",
139 "org.mycore.frontend.cli.MCRObjectCommands.repairMetadataSearchForID String",
140 "Read the SQL store table of MCRObject XML files with MCRObjectID {0} and restore them to the search store.");
141 command.add(com);
142
143 com = new MCRCommand("select objects with query {0}", "org.mycore.frontend.cli.MCRObjectCommands.selectObjectsWithQuery String",
144 "Select MCRObjects with MCRQueryString {0}.");
145 command.add(com);
146
147 com = new MCRCommand("delete selected", "org.mycore.frontend.cli.MCRObjectCommands.deleteSelected", "Removes selected MCRObjects.");
148 command.add(com);
149
150 com = new MCRCommand("export selected to directory {0} with {1}",
151 "org.mycore.frontend.cli.MCRObjectCommands.exportSelected String String",
152 "Stores selected MCRObjects to the directory {0} with the stylesheet {1}-object.xsl. For {1} save is the default.");
153 command.add(com);
154
155 com = new MCRCommand("remove selected from searchindex {0}",
156 "org.mycore.frontend.cli.MCRObjectCommands.removeFromSearchindex String",
157 "Remove selected MCRObjects from searchindex {0}.");
158 command.add(com);
159
160 com = new MCRCommand("check selected in sql store", "org.mycore.frontend.cli.MCRObjectCommands.checkSelected",
161 "Checks existence of selected MCRObjects in SQL store and deletes missing ones from search index.");
162 command.add(com);
163
164 com = new MCRCommand("check metadata search of type {0}", "org.mycore.frontend.cli.MCRObjectCommands.checkMetadataSearch String",
165 "Checks existence of MCRObjects of type {0} in search index and rapairs missing ones in search index.");
166 command.add(com);
167
168 com = new MCRCommand("set mode {0} of searcher for index {1}",
169 "org.mycore.frontend.cli.MCRObjectCommands.notifySearcher String String",
170 "Notify Searcher of Index {1} what is going on {0}.");
171 command.add(com);
172 }
173
174 public static void setSelectedObjectIDs(List<String> selected) {
175 MCRSessionMgr.getCurrentSession().put("mcrSelectedObjects", selected);
176 }
177
178 @SuppressWarnings("unchecked")
179 public static List<String> getSelectedObjectIDs() {
180 final List<String> list = (List<String>) MCRSessionMgr.getCurrentSession().get("mcrSelectedObjects");
181 if (list == null) {
182 return Collections.EMPTY_LIST;
183 }
184 return list;
185 }
186
187 /**
188 * Delete all MCRObject from the datastore for a given type.
189 *
190 * @param type
191 * the type of the MCRObjects that should be deleted
192 */
193 public static final List<String> deleteAllObjects(String type) throws MCRActiveLinkException {
194 final List<String> objectIds = MCRXMLTableManager.instance().retrieveAllIDs(type);
195 List<String> cmds = new ArrayList<String>(objectIds.size());
196 for (String id : objectIds) {
197 cmds.add("delete object " + id);
198 }
199 return cmds;
200 }
201
202 /**
203 * Delete a MCRObject from the datastore.
204 *
205 * @param ID
206 * the ID of the MCRObject that should be deleted
207 */
208 public static final void delete(String ID) throws MCRActiveLinkException {
209 MCRObject mycore_obj = new MCRObject();
210
211 try {
212 mycore_obj.deleteFromDatastore(ID);
213 LOGGER.info(mycore_obj.getId().getId() + " deleted.");
214 } catch (MCRException ex) {
215 LOGGER.error("Can't delete " + mycore_obj.getId().getId() + ".", ex);
216 }
217 }
218
219 /**
220 * Delete MCRObject's form ID to ID from the datastore.
221 *
222 * @param IDfrom
223 * the start ID for deleting the MCRObjects
224 * @param IDto
225 * the stop ID for deleting the MCRObjects
226 */
227 public static final void deleteFromTo(String IDfrom, String IDto) throws MCRActiveLinkException {
228 int from_i = 0;
229 int to_i = 0;
230
231 try {
232 MCRObjectID from = new MCRObjectID(IDfrom);
233 MCRObjectID to = new MCRObjectID(IDto);
234 MCRObjectID now = new MCRObjectID(IDfrom);
235 from_i = from.getNumberAsInteger();
236 to_i = to.getNumberAsInteger();
237
238 if (from_i > to_i) {
239 throw new MCRException("The from-to-interval is false.");
240 }
241
242 for (int i = from_i; i < (to_i + 1); i++) {
243 now.setNumber(i);
244 if (MCRObject.existInDatastore(now)) {
245 delete(now.getId());
246 }
247 }
248 } catch (MCRException ex) {
249 LOGGER.debug(ex.getStackTraceAsString());
250 LOGGER.error(ex.getMessage());
251 }
252 }
253
254 /**
255 * Load MCRObject's from all XML files in a directory.
256 *
257 * @param directory
258 * the directory containing the XML files
259 * @throws MCRActiveLinkException
260 */
261 public static final List<String> loadFromDirectory(String directory) throws MCRActiveLinkException {
262 return processFromDirectory(directory, false);
263 }
264
265 /**
266 * Update MCRObject's from all XML files in a directory.
267 *
268 * @param directory
269 * the directory containing the XML files
270 * @throws MCRActiveLinkException
271 */
272 public static final List<String> updateFromDirectory(String directory) throws MCRActiveLinkException {
273 return processFromDirectory(directory, true);
274 }
275
276 /**
277 * Load or update MCRObject's from all XML files in a directory.
278 *
279 * @param directory
280 * the directory containing the XML files
281 * @param update
282 * if true, object will be updated, else object is created
283 * @throws MCRActiveLinkException
284 */
285 private static final List<String> processFromDirectory(String directory, boolean update) throws MCRActiveLinkException {
286 File dir = new File(directory);
287
288 if (!dir.isDirectory()) {
289 LOGGER.warn(directory + " ignored, is not a directory.");
290 return null;
291 }
292
293 String[] list = dir.list();
294
295 if (list.length == 0) {
296 LOGGER.warn("No files found in directory " + directory);
297 return null;
298 }
299
300 List<String> cmds = new ArrayList<String>();
301 for (String file : list)
302 if (file.endsWith(".xml") && (!file.contains("derivate")))
303 cmds.add((update ? "update" : "load") + " object from file " + new File(dir, file).getAbsolutePath());
304
305 return cmds;
306 }
307
308 /**
309 * Load a MCRObjects from an XML file.
310 *
311 * @param file
312 * the location of the xml file
313 * @throws MCRActiveLinkException
314 */
315 public static final boolean loadFromFile(String file) throws MCRActiveLinkException {
316 return loadFromFile(file, true);
317 }
318
319 /**
320 * Load a MCRObjects from an XML file.
321 *
322 * @param file
323 * the location of the xml file
324 * @param importMode
325 * if true, servdates are taken from xml file
326 * @throws MCRActiveLinkException
327 */
328 public static final boolean loadFromFile(String file, boolean importMode) throws MCRActiveLinkException {
329 return processFromFile(new File(file), false, importMode);
330 }
331
332 /**
333 * Update a MCRObject's from an XML file.
334 *
335 * @param file
336 * the location of the xml file
337 * @throws MCRActiveLinkException
338 */
339 public static final boolean updateFromFile(String file) throws MCRActiveLinkException {
340 return updateFromFile(file, true);
341 }
342
343 /**
344 * Update a MCRObject's from an XML file.
345 *
346 * @param file
347 * the location of the xml file
348 * @param importMode
349 * if true, servdates are taken from xml file
350 * @throws MCRActiveLinkException
351 */
352 public static final boolean updateFromFile(String file, boolean importMode) throws MCRActiveLinkException {
353 return processFromFile(new File(file), true, importMode);
354 }
355
356 /**
357 * Load or update an MCRObject's from an XML file.
358 *
359 * @param file
360 * the location of the xml file
361 * @param update
362 * if true, object will be updated, else object is created
363 * @param importMode
364 * if true, servdates are taken from xml file
365 * @throws MCRActiveLinkException
366 */
367 private static final boolean processFromFile(File file, boolean update, boolean importMode) throws MCRActiveLinkException {
368 if (!file.getName().endsWith(".xml")) {
369 LOGGER.warn(file + " ignored, does not end with *.xml");
370 return false;
371 }
372
373 if (!file.isFile()) {
374 LOGGER.warn(file + " ignored, is not a file.");
375 return false;
376 }
377
378 LOGGER.info("Reading file " + file + " ...");
379
380 MCRObject mycore_obj = new MCRObject();
381 mycore_obj.setImportMode(importMode);
382 mycore_obj.setFromURI(file.toURI());
383 LOGGER.debug("Label --> " + mycore_obj.getLabel());
384
385 if (update) {
386 mycore_obj.updateInDatastore();
387 LOGGER.info(mycore_obj.getId().getId() + " updated.");
388 } else {
389 mycore_obj.createInDatastore();
390 LOGGER.info(mycore_obj.getId().getId() + " loaded.");
391 }
392
393 return true;
394 }
395
396 /**
397 * Shows the next free MCRObjectIDs.
398 *
399 * @param base
400 * the base String of the MCRObjectID
401 */
402 public static final void showNextID(String base) {
403 MCRObjectID mcr_id = new MCRObjectID();
404
405 try {
406 mcr_id.setNextFreeId(base);
407 LOGGER.info("The next free ID is " + mcr_id.getId());
408 } catch (MCRException ex) {
409 LOGGER.error(ex.getMessage());
410 }
411 }
412
413 /**
414 * Shows the last used MCRObjectIDs.
415 *
416 * @param base
417 * the base String of the MCRObjectID
418 */
419 public static final void showLastID(String base) {
420 MCRObjectID mcr_id = new MCRObjectID();
421
422 try {
423 mcr_id.setNextFreeId(base);
424 mcr_id.setNumber(mcr_id.getNumberAsInteger() - 1);
425 LOGGER.info("The last used ID is " + mcr_id.getId());
426 } catch (MCRException ex) {
427 LOGGER.error(ex.getMessage());
428 }
429 }
430
431 /**
432 * Export an MCRObject to a file named <em>MCRObjectID</em> .xml in a directory. The method use the converter stylesheet mcr_<em>style</em>_object.xsl.
433 *
434 * @param ID
435 * the ID of the MCRObject to be save.
436 * @param dirname
437 * the dirname to store the object
438 * @param style
439 * the type of the stylesheet
440 */
441 public static final void export(String ID, String dirname, String style) {
442 export(ID, ID, dirname, style);
443 }
444
445 /**
446 * Save any MCRObject's to files named <em>MCRObjectID</em> .xml in a directory. The saving starts with fromID and runs to toID. ID's they was not found
447 * will skiped. The method use the converter stylesheet mcr_<em>style</em>_object.xsl.
448 *
449 * @param fromID
450 * the ID of the MCRObject from be save.
451 * @param toID
452 * the ID of the MCRObject to be save.
453 * @param dirname
454 * the filename to store the object
455 * @param style
456 * the type of the stylesheet
457 */
458 public static final void export(String fromID, String toID, String dirname, String style) {
459 MCRObjectID fid, tid;
460
461 // check fromID and toID
462 try {
463 fid = new MCRObjectID(fromID);
464 tid = new MCRObjectID(toID);
465 } catch (Exception ex) {
466 LOGGER.error("FromID : " + ex.getMessage());
467 return;
468 }
469 // check dirname
470 File dir = new File(dirname);
471 if (!dir.isDirectory()) {
472 LOGGER.error(dirname + " is not a dirctory.");
473 return;
474 }
475
476 MCRObjectID nid = fid;
477 int k = 0;
478 try {
479 Transformer trans = getTransformer(style);
480 for (int i = fid.getNumberAsInteger(); i < (tid.getNumberAsInteger() + 1); i++) {
481 nid.setNumber(i);
482 if (!MCRObject.existInDatastore(nid)) {
483 continue;
484 }
485 if (!exportMCRObject(dir, trans, nid)) {
486 continue;
487 }
488 k++;
489 }
490 } catch (Exception ex) {
491 LOGGER.error(ex.getMessage());
492 LOGGER.error("Exception while store file to " + dir.getAbsolutePath());
493 return;
494 }
495 LOGGER.info(k + " Object's stored under " + dir.getAbsolutePath() + ".");
496 }
497
498 /**
499 * Save all MCRObject's to files named <em>MCRObjectID</em> .xml in a <em>dirname</em>directory for the data type <em>type</em>. The method use the
500 * converter stylesheet mcr_<em>style</em>_object.xsl.
501 *
502 * @param fromID
503 * the ID of the MCRObject from be save.
504 * @param toID
505 * the ID of the MCRObject to be save.
506 * @param dirname
507 * the filename to store the object
508 * @param style
509 * the type of the stylesheet
510 */
511 public static final List<String> exportAllObjects(String type, String dirname, String style) {
512 // check dirname
513 File dir = new File(dirname);
514
515 if (dir.isFile()) {
516 LOGGER.error(dirname + " is not a dirctory.");
517 return Collections.emptyList();
518 }
519 List<String> objectIds = MCRXMLTableManager.instance().retrieveAllIDs(type);
520 List<String> cmds = new ArrayList<String>(objectIds.size());
521 for (String id : objectIds) {
522 cmds.add(new StringBuilder("export object from ").append(id).append(" to ").append(id).append(" to directory ").append(dirname)
523 .append(" with ").append(style).toString());
524 }
525 return cmds;
526 }
527
528 /**
529 * The method search for a stylesheet mcr_<em>style</em>_object.xsl and build the transformer. Default is <em>mcr_save-object.xsl</em>.
530 *
531 * @param style
532 * the style attribute for the transformer stylesheet
533 * @return the transformer
534 * @throws TransformerFactoryConfigurationError
535 * @throws TransformerConfigurationException
536 */
537 private static final Transformer getTransformer(String style) throws TransformerFactoryConfigurationError,
538 TransformerConfigurationException {
539 String xslfile = DEFAULT_TRANSFORMER;
540 if ((style != null) && (style.trim().length() != 0)) {
541 xslfile = style + "-object.xsl";
542 }
543 Transformer trans = translist.get(xslfile);
544 if (trans != null) {
545 return trans;
546 }
547 LOGGER.debug("Will load transformer stylesheet " + xslfile + "for export.");
548
549 InputStream in = MCRObjectCommands.class.getResourceAsStream("/" + xslfile);
550 if (in == null) {
551 in = MCRObjectCommands.class.getResourceAsStream("/xsl/" + DEFAULT_TRANSFORMER);
552 }
553 try {
554 if (in != null) {
555 StreamSource source = new StreamSource(in);
556 TransformerFactory transfakt = TransformerFactory.newInstance();
557 transfakt.setURIResolver(MCRURIResolver.instance());
558 trans = transfakt.newTransformer(source);
559 translist.put(xslfile, trans);
560 return trans;
561 } else {
562 LOGGER.warn("Can't load transformer ressource " + xslfile + " or " + DEFAULT_TRANSFORMER + ".");
563 }
564 } catch (Exception e) {
565 LOGGER.warn("Error while load transformer ressource " + xslfile + " or " + DEFAULT_TRANSFORMER + ".");
566 if (LOGGER.isDebugEnabled()) {
567 e.printStackTrace();
568 }
569 }
570 return null;
571 }
572
573 /**
574 * The method read a MCRObject and use the transformer to write the data to a file. They are any steps to handel errors and save the damaged data.
575 * <ul>
576 * <li>Read data for object ID in the MCRObject, add ACL's and store it as checked and transformed XML. Return true.</li>
577 * <li>If it can't find a transformer instance (no script file found) it store the checked data with ACL's native in the file. Warning and return true.</li>
578 * <li>If it get an exception while build the MCRObject, it try to read the XML blob and stor it without check and ACL's to the file. Warning and return
579 * true.</li>
580 * <li>If it get an exception while store the native data without check, ACĂ–'s and transformation it return a warning and false.</li>
581 * </ul>
582 *
583 * @param dir
584 * the file instance to store
585 * @param trans
586 * the XML transformer
587 * @param nid
588 * the MCRObjectID
589 * @return true if the store was okay (see description), else return false
590 * @throws FileNotFoundException
591 * @throws TransformerException
592 * @throws IOException
593 */
594 private static final boolean exportMCRObject(File dir, Transformer trans, MCRObjectID nid) throws FileNotFoundException,
595 TransformerException, IOException {
596 byte[] xml = null;
597 try {
598 // if object do'snt exist - no exception is catched!
599 xml = MCRObject.receiveXMLFromDatastore(nid.toString());
600 } catch (MCRException ex) {
601 return false;
602 }
603
604 File xmlOutput = new File(dir, nid.toString() + ".xml");
605 FileOutputStream out = new FileOutputStream(xmlOutput);
606
607 if (trans != null) {
608 StreamResult sr = new StreamResult(out);
609 trans.transform(new org.jdom.transform.JDOMSource(MCRXMLHelper.parseXML(xml, false)), sr);
610 } else {
611 out.write(xml);
612 out.flush();
613 }
614 LOGGER.info("Object " + nid.toString() + " saved to " + xmlOutput.getCanonicalPath() + ".");
615 return true;
616 }
617
618 /**
619 * Get the next free MCRObjectID for the given MCRObjectID base.
620 *
621 * @param base
622 * the MCRObjectID base string
623 */
624 public static final void getNextID(String base) {
625 MCRObjectID id = new MCRObjectID();
626
627 try {
628 id.setNextFreeId(base);
629 LOGGER.info(id.getId());
630 } catch (MCRException ex) {
631 LOGGER.error(ex.getMessage());
632 }
633 }
634
635 /**
636 * Get the last used MCRObjectID for the given MCRObjectID base.
637 *
638 * @param base
639 * the MCRObjectID base string
640 */
641 public static final void getLastID(String base) {
642 LOGGER.info(MCRObjectID.getLastID(base).getId());
643 }
644
645 /**
646 * The method parse and check an XML file.
647 *
648 * @param fileName
649 * the location of the xml file
650 */
651 public static final boolean checkXMLFile(String fileName) {
652 if (!fileName.endsWith(".xml")) {
653 LOGGER.warn(fileName + " ignored, does not end with *.xml");
654
655 return false;
656 }
657
658 File file = new File(fileName);
659
660 if (!file.isFile()) {
661 LOGGER.warn(fileName + " ignored, is not a file.");
662
663 return false;
664 }
665
666 LOGGER.info("Reading file " + file + " ...");
667
668 if (MCRXMLHelper.parseURI(file.toURI()) != null) {
669 LOGGER.info("The file has no XML errors.");
670 }
671
672 return true;
673 }
674
675 /**
676 * The method start the repair of the metadata search for a given MCRObjectID type.
677 *
678 * @param type
679 * the MCRObjectID type
680 */
681 public static final List<String> repairMetadataSearch(String type) {
682 LOGGER.info("Start the repair for type " + type);
683 String typetest = CONFIG.getString("MCR.Metadata.Type." + type, "");
684
685 if (typetest.length() == 0) {
686 LOGGER.error("The type " + type + " was not found.");
687 return Collections.emptyList();
688 }
689 List<String> ar = (List<String>) MCRXMLTableManager.instance().retrieveAllIDs(type);
690 if (ar.size() == 0) {
691 LOGGER.warn("No ID's was found for type " + type + ".");
692 return Collections.emptyList();
693 }
694
695 removeFromIndex("objectType", type);
696 List<String> cmds = new ArrayList<String>(ar.size());
697
698 for (String stid : ar) {
699 cmds.add("repair metadata search of ID " + stid);
700 }
701 return cmds;
702
703 }
704
705 /**
706 * The method start the repair of the metadata search for a given MCRObjectID as String.
707 *
708 * @param id
709 * the MCRObjectID as String
710 */
711 public static final void repairMetadataSearchForID(String id) {
712 LOGGER.info("Start the repair for the ID " + id);
713
714 MCRObjectID mid = null;
715
716 try {
717 mid = new MCRObjectID(id);
718 } catch (Exception e) {
719 LOGGER.error("The String " + id + " is not a MCRObjectID.");
720 return;
721 }
722
723 removeFromIndex("id", id);
724
725 MCRObject obj = new MCRObject();
726 obj.repairPersitenceDatastore(mid);
727 LOGGER.info("Repaired " + mid.getId());
728 }
729
730 /**
731 * The method removes entries from searchindex.
732 *
733 * @param fieldname
734 * Name of field used to delete entries
735 * @param value
736 * Value of the field
737 */
738 private static final void removeFromIndex(String fieldname, String value) {
739 MCRFieldDef fd = MCRFieldDef.getDef(fieldname);
740 MCRSearcher searcher = getSearcherForField(fieldname);
741 MCRFieldValue fv = new MCRFieldValue(fd, value);
742 searcher.clearIndex(fieldname, fv.getValue());
743 }
744
745 private static final MCRSearcher getSearcherForField(String fieldname) {
746 MCRFieldDef fd = MCRFieldDef.getDef(fieldname);
747 String index = fd.getIndex();
748 return MCRSearcherFactory.getSearcherForIndex(index);
749 }
750
751 /**
752 * Builds a resulset with a query. Used in later command to do work with.
753 *
754 * @param querystring
755 * MCRQuery as String
756 */
757 public static final void selectObjectsWithQuery(String querystring) {
758 LOGGER.info("Build Resultset with query " + querystring);
759
760 MCRCondition cond = (new MCRQueryParser()).parse(querystring);
761 MCRQuery query = new MCRQuery(cond);
762 final MCRResults results = MCRQueryManager.search(query);
763 ArrayList<String> ids = new ArrayList<String>(results.getNumHits());
764 for (MCRHit hit : results) {
765 ids.add(hit.getID());
766 }
767 setSelectedObjectIDs(ids);
768
769 LOGGER.info("Resultset built");
770 }
771
772 /**
773 * Delete all selected MCRObjects from the datastore.
774 */
775 public static final void deleteSelected() throws MCRActiveLinkException {
776 LOGGER.info("Start removing selected MCRObjects");
777
778 if (null == getSelectedObjectIDs()) {
779 LOGGER.info("No Resultset to work with, use command \"select objects with query {0}\" to build one");
780 return;
781 }
782 for (String id : getSelectedObjectIDs()) {
783 delete(id);
784 }
785 LOGGER.info("Selected MCRObjects deleted");
786 }
787
788 /*
789 * Export selected MCRObjects to a file named <em>MCRObjectID</em> .xml in a directory. The method use the converter stylesheet
790 * mcr_<em>style</em>_object.xsl.
791 * @param dirname the dirname to store the object @param style the type of the stylesheet
792 */
793 public static final List<String> exportSelected(String dirname, String style) {
794 LOGGER.info("Start exporting selected MCRObjects");
795
796 if (null == getSelectedObjectIDs()) {
797 LOGGER.info("No Resultset to work with, use command \"select objects with query {0}\" to build one");
798 return Collections.emptyList();
799 }
800 List<String> cmds = new ArrayList<String>(getSelectedObjectIDs().size());
801 for (String id : getSelectedObjectIDs()) {
802 cmds.add(new StringBuilder("export object from ").append(id).append(" to ").append(id).append(" to directory ").append(dirname)
803 .append(" with ").append(style).toString());
804 }
805 return cmds;
806 }
807
808 /**
809 * The method removes all selected entries from search index.
810 *
811 * @param index
812 * index of searcher
813 */
814 public static final void removeFromSearchindex(String index) {
815 LOGGER.info("Start removing selected entries from search index " + index);
816
817 MCRSearcher searcher = MCRSearcherFactory.getSearcherForIndex(index);
818
819 if (null == getSelectedObjectIDs()) {
820 LOGGER.info("No Resultset to work with, use command \"select objects with query {0}\" to build one");
821 return;
822 }
823 for (String id : getSelectedObjectIDs()) {
824 searcher.removeFromIndex(id);
825 }
826 LOGGER.info("Selected entries from search index removed");
827 }
828
829 /**
830 * The method checks the existence of selected MCRObjects in SQL store.
831 */
832 public static final void checkSelected() {
833 LOGGER.info("Start checking existence of selected MCRObjects in sql store");
834
835 if (null == getSelectedObjectIDs()) {
836 LOGGER.info("No Resultset to work with, use command \"select objects with query {0}\" to build one");
837 return;
838 }
839
840 int instore = 0;
841 int notinstore = 0;
842
843 for (String id : getSelectedObjectIDs()) {
844 if (MCRObject.existInDatastore(id)) {
845 instore++;
846 } else {
847 LOGGER.info("is not in store " + id + " delete from search index ...");
848 removeFromIndex("id", id);
849 notinstore++;
850 }
851 }
852
853 LOGGER.info("entries in Resultset : " + getSelectedObjectIDs().size());
854 LOGGER.info("entries in SQL Store : " + instore);
855 LOGGER.info("entries NOT in SQL Store: " + notinstore);
856 }
857
858 /**
859 * Checks existence of MCRObjectID type {0} in search index and rapairs missing ones in search index.
860 *
861 * @param type
862 * the MCRObjectID type
863 */
864 public static final void checkMetadataSearch(String type) {
865 LOGGER.info("Start the check for type " + type);
866 String typetest = CONFIG.getString("MCR.Metadata.Type." + type, "");
867
868 if (typetest.length() == 0) {
869 LOGGER.error("The type " + type + " was not found.");
870 return;
871 }
872 List<String> ar = (List<String>) MCRXMLTableManager.instance().retrieveAllIDs(type);
873 if (ar.size() == 0) {
874 LOGGER.warn("No ID's was found for type " + type + ".");
875 return;
876 }
877
878 for (String stid : ar) {
879 String querystring = "id = " + stid;
880 MCRCondition cond = (new MCRQueryParser()).parse(querystring);
881 MCRQuery query = new MCRQuery(cond);
882 MCRResults results = MCRQueryManager.search(query);
883 if (1 != results.getNumHits()) {
884 repairMetadataSearchForID(stid);
885 }
886 }
887 }
888
889 /**
890 * Inform Searcher what is going on.
891 *
892 * @param mode
893 * what is going on, for example rebuild insert ... finish
894 * @param index
895 * of searcher
896 */
897 public static final void notifySearcher(String mode, String index) {
898 MCRSearcher searcher = MCRSearcherFactory.getSearcherForIndex(index);
899 searcher.notifySearcher(mode);
900 }
901 }