001 /**
002 *
003 * $Revision: 15270 $ $Date: 2009-05-25 17:27:57 +0200 (Mon, 25 May 2009) $
004 *
005 * This file is part of ** M y C o R e **
006 * Visit our homepage at http://www.mycore.de/ for details.
007 *
008 * This program is free software; you can use it, redistribute it
009 * and / or modify it under the terms of the GNU General Public License
010 * (GPL) as published by the Free Software Foundation; either version 2
011 * of the License or (at your option) any later version.
012 *
013 * This program is distributed in the hope that it will be useful, but
014 * WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program, normally in the file license.txt.
020 * If not, write to the Free Software Foundation Inc.,
021 * 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
022 *
023 **/
024 package org.mycore.frontend.cli;
025
026 import java.io.File;
027 import java.io.FileOutputStream;
028 import java.io.InputStream;
029 import java.net.URISyntaxException;
030 import java.util.ArrayList;
031 import java.util.List;
032
033 import javax.xml.transform.Transformer;
034 import javax.xml.transform.TransformerConfigurationException;
035 import javax.xml.transform.TransformerFactory;
036 import javax.xml.transform.TransformerFactoryConfigurationError;
037 import javax.xml.transform.stream.StreamResult;
038 import javax.xml.transform.stream.StreamSource;
039
040 import org.apache.log4j.Logger;
041 import org.jdom.Document;
042 import org.jdom.output.Format;
043 import org.jdom.output.XMLOutputter;
044
045 import org.mycore.common.xml.MCRURIResolver;
046 import org.mycore.common.xml.MCRXMLHelper;
047 import org.mycore.datamodel.classifications2.MCRCategory;
048 import org.mycore.datamodel.classifications2.MCRCategoryDAO;
049 import org.mycore.datamodel.classifications2.MCRCategoryID;
050 import org.mycore.datamodel.classifications2.MCRLabel;
051 import org.mycore.datamodel.classifications2.impl.MCRCategoryDAOImpl;
052 import org.mycore.datamodel.classifications2.utils.MCRCategoryTransformer;
053 import org.mycore.datamodel.classifications2.utils.MCRXMLTransformer;
054 import org.mycore.datamodel.common.MCRActiveLinkException;
055
056 /**
057 * Commands for the classification system.
058 *
059 * @author Thomas Scheffler (yagee)
060 */
061 public class MCRClassification2Commands extends MCRAbstractCommands {
062 private static Logger LOGGER = Logger.getLogger(MCRClassification2Commands.class);
063
064 private static final MCRCategoryDAO DAO = new MCRCategoryDAOImpl();
065
066 /** Default transformer script */
067 public static final String DEFAULT_TRANSFORMER = "save-classification.xsl";
068
069 public MCRClassification2Commands() {
070 command.add(new MCRCommand("load classification from file {0}", "org.mycore.frontend.cli.MCRClassification2Commands.loadFromFile String", "The command add a new classification form file {0} to the system."));
071 command.add(new MCRCommand("update classification from file {0}", "org.mycore.frontend.cli.MCRClassification2Commands.updateFromFile String", "The command add a new classification form file {0} to the system."));
072 command.add(new MCRCommand("delete classification {0}", "org.mycore.frontend.cli.MCRClassification2Commands.delete String", "The command remove the classification with MCRObjectID {0} from the system."));
073 command.add(new MCRCommand("load all classifications from directory {0}", "org.mycore.frontend.cli.MCRClassification2Commands.loadFromDirectory String", "The command add all classifications in the directory {0} to the system."));
074 command.add(new MCRCommand("update all classifications from directory {0}", "org.mycore.frontend.cli.MCRClassification2Commands.updateFromDirectory String", "The command update all classifications in the directory {0} to the system."));
075 command.add(new MCRCommand("export classification {0} to {1} with {2}", "org.mycore.frontend.cli.MCRClassification2Commands.export String String String", "The command store the classification with MCRObjectID {0} to the file named {1} with the stylesheet {2}-object.xsl. For {2} save is the default.."));
076 command.add(new MCRCommand("export all classifications to {0} with {1}", "org.mycore.frontend.cli.MCRClassification2Commands.exportAll String String", "The command store all classifications to the directory with name {0} with the stylesheet {1}-object.xsl. For {1} save is the default."));
077 command.add(new MCRCommand("count classification children of {0}", "org.mycore.frontend.cli.MCRClassification2Commands.countChildren String", "The command remove the classification with MCRObjectID {0} from the system."));
078 command.add(new MCRCommand("list classification {0}", "org.mycore.frontend.cli.MCRClassification2Commands.listClassification String", "The command list the classification with MCRObjectID {0}."));
079 command.add(new MCRCommand("list all classifications", "org.mycore.frontend.cli.MCRClassification2Commands.listAllClassifications", "The command list all classification stored in the database."));
080 }
081
082 /**
083 * Deletes a classification
084 *
085 * @param classID
086 * @see MCRCategoryDAO#deleteCategory(MCRCategoryID)
087 */
088 public static void delete(String classID) {
089 DAO.deleteCategory(MCRCategoryID.rootID(classID));
090 }
091
092 /**
093 * Deletes a classification
094 *
095 * @param classID
096 * @see MCRCategoryDAO#deleteCategory(MCRCategoryID)
097 */
098 public static void countChildren(String classID) {
099 MCRCategory category = DAO.getCategory(MCRCategoryID.rootID(classID), -1);
100 System.out.printf("%s has %d children", category.getId(), category.getChildren().size());
101 }
102
103 /**
104 * Adds a classification.
105 *
106 * Classification is built from a file.
107 *
108 * @param filname
109 * file in mcrclass xml format
110 * @throws URISyntaxException
111 * @see MCRCategoryDAO#addCategory(MCRCategoryID, MCRCategory)
112 */
113 public static void loadFromFile(String filename) throws URISyntaxException {
114 File file = new File(filename);
115 Document xml = MCRXMLHelper.parseURI(file.toURI());
116 MCRCategory category = MCRXMLTransformer.getCategory(xml);
117 DAO.addCategory(null, category);
118 }
119
120 /**
121 * Replaces a classification with a new version
122 *
123 * @param filename
124 * file in mcrclass xml format
125 * @throws URISyntaxException
126 * @see MCRCategoryDAO#replaceCategory(MCRCategory)
127 */
128 public static void updateFromFile(String filename) throws URISyntaxException {
129 File file = new File(filename);
130 Document xml = MCRXMLHelper.parseURI(file.toURI());
131 MCRCategory category = MCRXMLTransformer.getCategory(xml);
132 if (DAO.exist(category.getId())) {
133 DAO.replaceCategory(category);
134 } else {
135 // add if classification does not exist
136 DAO.addCategory(null, category);
137 }
138 }
139
140 /**
141 * Loads MCRClassification from all XML files in a directory.
142 *
143 * @param directory
144 * the directory containing the XML files
145 * @throws MCRActiveLinkException
146 */
147 public static List<String> loadFromDirectory(String directory) throws MCRActiveLinkException {
148 return processFromDirectory(directory, false);
149 }
150
151 /**
152 * Updates MCRClassification from all XML files in a directory.
153 *
154 * @param directory
155 * the directory containing the XML files
156 * @throws MCRActiveLinkException
157 */
158 public static List<String> updateFromDirectory(String directory) throws MCRActiveLinkException {
159 return processFromDirectory(directory, true);
160 }
161
162 /**
163 * Loads or updates MCRClassification from all XML files in a directory.
164 *
165 * @param directory
166 * the directory containing the XML files
167 * @param update
168 * if true, classification will be updated, else Classification
169 * is created
170 * @throws MCRActiveLinkException
171 */
172 private static List<String> processFromDirectory(String directory, boolean update) throws MCRActiveLinkException {
173 File dir = new File(directory);
174
175 if (!dir.isDirectory()) {
176 LOGGER.warn(directory + " ignored, is not a directory.");
177 return null;
178 }
179
180 String[] list = dir.list();
181
182 if (list.length == 0) {
183 LOGGER.warn("No files found in directory " + directory);
184 return null;
185 }
186
187 List<String> cmds = new ArrayList<String>();
188 for (String file : list)
189 if (file.endsWith(".xml"))
190 cmds.add((update ? "update" : "load") + " classification from file " + new File(dir, file).getAbsolutePath());
191
192 return cmds;
193 }
194
195 /**
196 * Save a MCRClassification.
197 *
198 * @param ID
199 * the ID of the MCRClassification to be save.
200 * @param filename
201 * the filename to store the classification
202 * @param style
203 * the name part of the stylesheet like <em>style</em>
204 * -classification.xsl
205 * @return false if an error was occured, else true
206 */
207 public static boolean export(String ID, String dirname, String style) throws Exception {
208 String dname = "";
209 if (dirname.length() != 0) {
210 try {
211 File dir = new File(dirname);
212 if (!dir.isDirectory()) {
213 dir.mkdir();
214 }
215 if (!dir.isDirectory()) {
216 LOGGER.error("Can't find or create directory " + dir.getAbsolutePath());
217 return false;
218 } else {
219 dname = dirname;
220 }
221 } catch (Exception e) {
222 LOGGER.error("Can't find or create directory " + dirname, e);
223 return false;
224 }
225 }
226 MCRCategory cl = DAO.getCategory(MCRCategoryID.rootID(ID), -1);
227 Document classDoc = MCRCategoryTransformer.getMetaDataDocument(cl, false);
228
229 Transformer trans = getTransformer(style);
230 File xmlOutput = new File(dname, ID + ".xml");
231 FileOutputStream out = new FileOutputStream(xmlOutput);
232 if (trans != null) {
233 StreamResult sr = new StreamResult(out);
234 trans.transform(new org.jdom.transform.JDOMSource(classDoc), sr);
235 } else {
236 XMLOutputter xout = new XMLOutputter(Format.getPrettyFormat());
237 xout.output(classDoc, out);
238 out.flush();
239 }
240 LOGGER.info("Classifcation " + ID + " saved to " + xmlOutput.getCanonicalPath() + ".");
241 return true;
242 }
243
244 /**
245 * The method search for a stylesheet mcr_<em>style</em>_object.xsl and
246 * build the transformer. Default is <em>mcr_save-object.xsl</em>.
247 *
248 * @param style
249 * the style attribute for the transformer stylesheet
250 * @return the transformer
251 * @throws TransformerFactoryConfigurationError
252 * @throws TransformerConfigurationException
253 */
254 private static final Transformer getTransformer(String style) throws TransformerFactoryConfigurationError, TransformerConfigurationException {
255 String xslfile = DEFAULT_TRANSFORMER;
256 if ((style != null) && (style.trim().length() != 0)) {
257 xslfile = style + "-classification.xsl";
258 }
259 Transformer trans = null;
260
261 InputStream in = MCRClassification2Commands.class.getResourceAsStream("/" + xslfile);
262 if (in == null) {
263 in = MCRClassification2Commands.class.getResourceAsStream(DEFAULT_TRANSFORMER);
264 }
265 if (in != null) {
266 StreamSource source = new StreamSource(in);
267 TransformerFactory transfakt = TransformerFactory.newInstance();
268 transfakt.setURIResolver(MCRURIResolver.instance());
269 trans = transfakt.newTransformer(source);
270 }
271 return trans;
272 }
273
274 /**
275 * Save all MCRClassifications.
276 *
277 * @param dirname
278 * the directory name to store all classifications
279 * @param style
280 * the name part of the stylesheet like <em>style</em>
281 * -classification.xsl
282 * @return false if an error was occured, else true
283 */
284 public static boolean exportAll(String dirname, String style) throws Exception {
285 List<MCRCategoryID> allClassIds = DAO.getRootCategoryIDs();
286 boolean ret = false;
287 for (MCRCategoryID id : allClassIds) {
288 ret = ret & export(id.getRootID(), dirname, style);
289 }
290 return ret;
291 }
292
293 /**
294 * List all IDs of all classifications stored in the database
295 */
296 public static void listAllClassifications() {
297 List<MCRCategoryID> allClassIds = DAO.getRootCategoryIDs();
298 for (MCRCategoryID id : allClassIds) {
299 LOGGER.info(id.getRootID());
300 }
301 LOGGER.info("");
302 }
303
304 /**
305 * List a MCRClassification.
306 *
307 * @param classid
308 * the MCRObjectID of the classification
309 */
310 public static void listClassification(String classid) {
311 MCRCategoryID clid = MCRCategoryID.rootID(classid);
312 MCRCategory cl = DAO.getCategory(clid, -1);
313 LOGGER.info(classid);
314 if (cl != null) {
315 listCategory(cl);
316 } else {
317 LOGGER.error("Can't find classification " + classid);
318 }
319 }
320
321 private static void listCategory(MCRCategory categ) {
322 int level = categ.getLevel();
323 StringBuffer sb = new StringBuffer(128);
324 for (int i = 0; i < level * 2; i++) {
325 sb.append(' ');
326 }
327 String space = sb.toString();
328 if (categ.isCategory()) {
329 LOGGER.info(space + " ID : " + categ.getId().getID());
330 }
331 for (MCRLabel label : categ.getLabels()) {
332 LOGGER.info(space + " Label : (" + label.getLang() + ") " + label.getText());
333 }
334 List<MCRCategory> children = categ.getChildren();
335 for (MCRCategory child : children) {
336 listCategory(child);
337 }
338 }
339 }