001 /*
002 * $Revision: 13278 $ $Date: 2008-03-17 17:12:15 +0100 (Mo, 17 Mrz 2008) $
003 *
004 * This file is part of *** M y C o R e ***
005 * See http://www.mycore.de/ for details.
006 *
007 * This program is free software; you can use it, redistribute it
008 * and / or modify it under the terms of the GNU General Public License
009 * (GPL) as published by the Free Software Foundation; either version 2
010 * of the License or (at your option) any later version.
011 *
012 * This program is distributed in the hope that it will be useful, but
013 * WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015 * GNU General Public License for more details.
016 *
017 * You should have received a copy of the GNU General Public License
018 * along with this program, in a file called gpl.txt or license.txt.
019 * If not, write to the Free Software Foundation Inc.,
020 * 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
021 */
022
023 package org.mycore.frontend.servlets;
024
025 import java.io.IOException;
026 import java.net.URLEncoder;
027 import java.util.ArrayList;
028 import java.util.Collections;
029 import java.util.Comparator;
030 import java.util.Iterator;
031 import java.util.List;
032 import java.util.Map;
033
034 import javax.servlet.http.HttpServletRequest;
035
036 import org.apache.log4j.Logger;
037 import org.jdom.Document;
038 import org.jdom.Element;
039
040 import org.mycore.common.MCRConfigurationException;
041 import org.mycore.common.MCRException;
042 import org.mycore.datamodel.classifications2.MCRCategLinkServiceFactory;
043 import org.mycore.datamodel.classifications2.MCRCategory;
044 import org.mycore.datamodel.classifications2.MCRCategoryDAOFactory;
045 import org.mycore.datamodel.classifications2.MCRCategoryID;
046 import org.mycore.datamodel.classifications2.MCRLabel;
047 import org.mycore.parsers.bool.MCRAndCondition;
048 import org.mycore.parsers.bool.MCRCondition;
049 import org.mycore.services.fieldquery.MCRFieldDef;
050 import org.mycore.services.fieldquery.MCRQuery;
051 import org.mycore.services.fieldquery.MCRQueryCondition;
052 import org.mycore.services.fieldquery.MCRQueryManager;
053 import org.mycore.services.fieldquery.MCRQueryParser;
054
055 /**
056 * This servlet provides a way to visually navigate through the tree of
057 * categories of a classification. The XML output is transformed to HTML
058 * using classificationBrowserData.xsl on the server side, then sent to
059 * the client browser, where AJAX does the rest.
060 *
061 * @author Frank Lützenkirchen
062 */
063 public class MCRClassificationBrowser2 extends MCRServlet {
064 private static final long serialVersionUID = 1L;
065
066 private static final Logger LOGGER = Logger.getLogger(MCRClassificationBrowser2.class);
067
068 public void doGetPost(MCRServletJob job) throws Exception {
069 long time = System.nanoTime();
070
071 HttpServletRequest req = job.getRequest();
072
073 String classifID = req.getParameter("classification");
074 String categID = req.getParameter("category");
075 String objectType = req.getParameter("objecttype");
076 String field = req.getParameter("field");
077 String restriction = req.getParameter("restriction");
078 String parameters = req.getParameter("parameters");
079
080 boolean countResults = Boolean.valueOf(req.getParameter("countresults"));
081 boolean uri = Boolean.valueOf(req.getParameter("adduri"));
082
083 String el = req.getParameter("emptyleaves");
084 boolean emptyLeaves = true;
085 if ((el != null) && (el.trim().length() > 0))
086 emptyLeaves = Boolean.valueOf(el);
087
088 LOGGER.info("ClassificationBrowser " + classifID + " " + (categID == null ? "" : categID));
089
090 MCRCategoryID id = new MCRCategoryID(classifID, categID);
091 Element xml = new Element("classificationBrowserData");
092 xml.setAttribute("classification", classifID);
093 xml.setAttribute("webpage", req.getParameter("webpage"));
094
095 MCRAndCondition queryCondition = new MCRAndCondition();
096 final MCRFieldDef fieldDef = MCRFieldDef.getDef(field);
097 if (fieldDef == null)
098 throw new MCRConfigurationException("Search field '" + field + "' is not defined.");
099 MCRQueryCondition categCondition = new MCRQueryCondition(fieldDef, "=", "DUMMY");
100 queryCondition.addChild(categCondition);
101
102 if ((objectType != null) && (objectType.trim().length() > 0)) {
103 xml.setAttribute("objectType", objectType);
104 MCRCondition cond = new MCRQueryCondition(MCRFieldDef.getDef("objectType"), "=", objectType);
105 queryCondition.addChild(cond);
106 }
107 if ((restriction != null) && (restriction.trim().length() > 0)) {
108 MCRCondition cond = new MCRQueryParser().parse(restriction);
109 queryCondition.addChild(cond);
110 }
111
112 if (parameters != null)
113 xml.setAttribute("parameters", parameters);
114
115 List<Element> data = new ArrayList<Element>();
116 MCRCategory category = MCRCategoryDAOFactory.getInstance().getCategory(id, 1);
117 for (MCRCategory child : category.getChildren()) {
118 String childID = child.getId().getID();
119 categCondition.setValue(childID);
120 int numResults = (countResults ? MCRQueryManager.search(new MCRQuery(queryCondition)).getNumHits() : 1);
121
122 if ((!emptyLeaves) && (numResults < 1))
123 continue;
124
125 Element categoryE = new Element("category");
126 data.add(categoryE);
127 if (countResults)
128 categoryE.setAttribute("numResults", String.valueOf(numResults));
129
130 categoryE.setAttribute("id", childID);
131 categoryE.setAttribute("children", Boolean.toString(child.hasChildren()));
132
133 categoryE.setAttribute("query", URLEncoder.encode(queryCondition.toString(), "UTF-8"));
134
135 if (uri && (child.getURI() != null))
136 categoryE.addContent(new Element("uri").setText(child.getURI().toString()));
137
138 addLabel(req, child, categoryE);
139 }
140
141 countLinks(req, emptyLeaves, objectType, category, data);
142 sortCategories(req, data);
143 xml.addContent(data);
144 renderToHTML(job, req, xml);
145
146 time = (System.nanoTime() - time) / 1000000;
147 LOGGER.info("ClassificationBrowser finished in " + time + " ms");
148 }
149
150 /**
151 * Add label in current lang, otherwise default lang, optional with
152 * description
153 */
154 private void addLabel(HttpServletRequest req, MCRCategory child, Element category) {
155 MCRLabel label = child.getCurrentLabel();
156
157 category.addContent(new Element("label").setText(label.getText()));
158
159 // if true, add description
160 boolean descr = Boolean.valueOf(req.getParameter("adddescription"));
161 if (descr && (label.getDescription() != null))
162 category.addContent(new Element("description").setText(label.getDescription()));
163 }
164
165 /** Add link count to each category */
166 private void countLinks(HttpServletRequest req, boolean emptyLeaves, String objectType, MCRCategory category, List<Element> data) {
167 if (!Boolean.valueOf(req.getParameter("countlinks")))
168 return;
169 if (objectType.trim().length() == 0)
170 objectType = null;
171 String classifID = category.getId().getRootID();
172 Map<MCRCategoryID, Number> count = MCRCategLinkServiceFactory.getInstance().countLinksForType(category, objectType, true);
173 for (Iterator<Element> it = data.iterator(); it.hasNext();) {
174 Element child = it.next();
175 MCRCategoryID childID = new MCRCategoryID(classifID, child.getAttributeValue("id"));
176 int num = (count.containsKey(childID) ? count.get(childID).intValue() : 0);
177 child.setAttribute("numLinks", String.valueOf(num));
178 if ((!emptyLeaves) && (num < 1))
179 it.remove();
180 }
181 }
182
183 /** Sorts by id, by label in current language, or keeps natural order */
184 private void sortCategories(HttpServletRequest req, List<Element> data) {
185 final String sortBy = req.getParameter("sortby");
186 if (sortBy != null)
187 Collections.sort(data, new Comparator<Element>() {
188 public int compare(Element a, Element b) {
189 if ("id".equals(sortBy))
190 return (a.getAttributeValue("id").compareTo(b.getAttributeValue("id")));
191 else if ("label".equals(sortBy))
192 return (a.getChildText("label").compareToIgnoreCase(b.getChildText("label")));
193 else
194 return 0;
195 }
196 });
197 }
198
199 /** Sends output to client browser */
200 private void renderToHTML(MCRServletJob job, HttpServletRequest req, Element xml) throws IOException {
201 String style = req.getParameter("style"); // XSL.Style, optional
202 if ((style != null) && (style.length() > 0))
203 req.setAttribute("XSL.Style", style);
204
205 MCRServlet.getLayoutService().doLayout(req, job.getResponse(), new Document(xml));
206 }
207 }