001 /*
002 * $RCSfile: MergeProperties.java,v $
003 * $Revision: 1.2 $ $Date: 2006/11/22 10:50:21 $
004 *
005 * This file is part of *** M y C o R e ***
006 * See 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, in a file called gpl.txt or 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 package org.mycore.buildtools.anttasks;
024
025 import java.io.File;
026 import java.io.FileInputStream;
027 import java.io.FileOutputStream;
028 import java.io.InputStreamReader;
029 import java.io.OutputStreamWriter;
030 import java.nio.channels.FileChannel;
031 import java.util.Arrays;
032 import java.util.HashSet;
033 import java.util.Set;
034
035 import javax.xml.parsers.DocumentBuilder;
036 import javax.xml.parsers.DocumentBuilderFactory;
037
038 import org.apache.tools.ant.BuildException;
039 import org.apache.tools.ant.Task;
040 import org.apache.xml.serialize.OutputFormat;
041 import org.apache.xml.serialize.XMLSerializer;
042 import org.w3c.dom.Document;
043 import org.w3c.dom.Element;
044 import org.w3c.dom.Node;
045 import org.w3c.dom.NodeList;
046 import org.xml.sax.InputSource;
047
048 /**
049 * Ant task, that can be used to merges one searchfield.xml file into another.
050 * New indexes will be added. It depends on the boolean flag overwrite, if the
051 * paths and object types for existing indexes will be overwritten or
052 * concatenated .
053 *
054 * @author Robert Stephan
055 *
056 * @version $Revision: 13085 $ $Date: 2008-02-06 18:27:24 +0100 (Mi, 06 Feb
057 * 2008) $
058 *
059 */
060 public class MCRMergeSearchfieldsXMLTask extends Task {
061 private String base, delta, out;
062 private boolean overwrite = false;
063
064 /**
065 * set the base searchfield.xml file
066 *
067 * @param f
068 * the base searchfield.xml file
069 */
070 public void setBasefile(String f) {
071 base = f;
072 out = f;
073 }
074
075 /**
076 * set the delta searchfield.xml file
077 *
078 * @param f
079 * the delta searchfield.xml file
080 */
081 public void setDeltafile(String f) {
082 delta = f;
083 }
084
085 /**
086 * sets the overwrite flag when set exisiting object type and path values
087 * will be overwritten
088 *
089 * @param b
090 */
091 public void setOverwrite(boolean b) {
092 overwrite = b;
093 }
094
095 /*
096 * (non-Javadoc)
097 *
098 * @see org.apache.tools.ant.Task#execute()
099 */
100 public void execute() throws BuildException {
101 try {
102 DocumentBuilderFactory factory = DocumentBuilderFactory
103 .newInstance();
104 factory.setValidating(false);
105 factory.setIgnoringElementContentWhitespace(true);
106 DocumentBuilder builder = factory.newDocumentBuilder();
107 Document docBase = builder.parse(new InputSource(
108 new InputStreamReader(new FileInputStream(new File(base)),
109 "UTF-8")));
110 docBase.normalize();
111
112 Document docDelta = builder.parse(new InputSource(
113 new InputStreamReader(new FileInputStream(new File(delta)),
114 "UTF-8")));
115 docDelta.normalize();
116
117 merge(docBase, docDelta);
118 docBase.normalize();
119
120 // output
121 // TransformerFactory tFactory = TransformerFactory.newInstance();
122 // Transformer transformer = tFactory.newTransformer();
123 // transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
124 // transformer.setOutputProperty(OutputKeys.METHOD,"xml");
125 // transformer.setOutputProperty(OutputKeys.INDENT, "true");
126 // transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount",
127 // "4");
128 // DOMSource source = new DOMSource(docBase);
129 // StreamResult result = new StreamResult(new FileOutputStream(new
130 // File(out)));
131 // transformer.transform(source, result);
132
133 // alternative code for output (with "pretty print")
134 OutputFormat format = new OutputFormat(docBase);
135 format.setLineWidth(360);
136 format.setIndenting(true);
137 format.setIndent(4);
138 XMLSerializer serializer = new XMLSerializer(
139 new OutputStreamWriter(new FileOutputStream(new File(out)),
140 "UTF-8"), format);
141 serializer.serialize(docBase);
142
143 } catch (Exception e) {
144 throw new BuildException(
145 "Something went wrong while merging searchfields!", e);
146 }
147 }
148
149 /**
150 * simple test case for the class
151 * @param args the default arguments for main method (unused)
152 */
153 public static void main(String[] args) {
154 String basefile = "C:\\mycore\\modules\\buildtools\\test\\searchfields\\searchfields.org.xml";
155 String deltafile = "C:\\mycore\\modules\\buildtools\\test\\searchfields\\othersearchfields.xml";
156 String outfile = "C:\\mycore\\modules\\buildtools\\test\\searchfields\\searchfields.xml";
157
158 // copy the file;
159 try {
160 FileChannel ic = new FileInputStream(basefile).getChannel();
161 FileChannel oc = new FileOutputStream(outfile).getChannel();
162 ic.transferTo(0, ic.size(), oc);
163 ic.close();
164 oc.close();
165 } catch (Exception e) {
166 e.printStackTrace();
167 }
168
169 MCRMergeSearchfieldsXMLTask mx = new MCRMergeSearchfieldsXMLTask();
170 mx.setBasefile(outfile);
171 mx.setDeltafile(deltafile);
172
173 mx.execute();
174 System.out.println("OK");
175
176 }
177
178 private void merge(Document docBase, Document docDelta) {
179 NodeList nlDeltaElemIndex = docDelta.getDocumentElement()
180 .getElementsByTagName("index");
181 for (int i = 0; i < nlDeltaElemIndex.getLength(); i++) {
182 Element eDeltaIndex = (Element) nlDeltaElemIndex.item(i);
183 // System.out.println(eDeltaIndex.getAttribute("id"));
184 Element eBaseIndex = findIndexElement(eDeltaIndex
185 .getAttribute("id"), docBase);
186 mergeIndexElements(eBaseIndex, eDeltaIndex);
187 }
188 }
189
190 private Element findIndexElement(String id, Document doc) {
191 NodeList nlElemIndex = doc.getDocumentElement().getElementsByTagName(
192 "index");
193 for (int i = 0; i < nlElemIndex.getLength(); i++) {
194 Element elem = (Element) nlElemIndex.item(i);
195 if (elem.getAttribute("id").equals(id)) {
196 return elem;
197 }
198 }
199 // Element has not been found -> create index element
200 Element index = doc.createElement("index");
201 index.setAttribute("id", id);
202 doc.getDocumentElement().appendChild(index);
203 return index;
204 }
205
206 private void mergeIndexElements(Element eBaseIndex, Element eDeltaIndex) {
207 NodeList nlDeltaElemField = eDeltaIndex.getElementsByTagName("field");
208 for (int i = 0; i < nlDeltaElemField.getLength(); i++) {
209 Element eDeltaField = (Element) nlDeltaElemField.item(i);
210 // System.out.println("+--- "+ eDeltaField.getAttribute("name"));
211 Element eBaseField = findFieldElement(eDeltaField
212 .getAttribute("name"), eBaseIndex);
213 if (overwrite) {
214 overwriteField(eBaseField, eDeltaField);
215 } else {
216 mergeField(eBaseField, eDeltaField);
217 }
218 }
219 }
220
221 private Element findFieldElement(String name, Element eIndex) {
222 NodeList nlElemField = eIndex.getElementsByTagName("field");
223 for (int i = 0; i < nlElemField.getLength(); i++) {
224 Element elem = (Element) nlElemField.item(i);
225 if (elem.getAttribute("name").equals(name)) {
226 return elem;
227 }
228 }
229 // Element has not been found -> create index element
230 Element field = eIndex.getOwnerDocument().createElement("field");
231 field.setAttribute("name", name);
232 eIndex.appendChild(field);
233 return field;
234 }
235
236 private void mergeField(Element eBaseField, Element eDeltaField) {
237 // attributes source and type must be equal
238 if (!eBaseField.getAttribute("source").equals("")
239 && !eDeltaField.getAttribute("source").equals("")
240 && !eBaseField.getAttribute("source").equals(
241 eDeltaField.getAttribute("source"))) {
242 throw new BuildException("Attributes source of field "
243 + eBaseField.getAttribute("name")
244 + " must be equal to be merged!" + "\n base file : "
245 + base + "\n delta file: " + delta);
246 }
247 if (!eBaseField.getAttribute("type").equals("")
248 && !eDeltaField.getAttribute("type").equals("")
249 && !eBaseField.getAttribute("type").equals(
250 eDeltaField.getAttribute("type"))) {
251 throw new BuildException("Attributes type of field "
252 + eBaseField.getAttribute("name")
253 + " must be equal to be merged!" + "\n base file : "
254 + base + "\n delta file: " + delta);
255 }
256 // attribute objects (separated by space)
257 if (!eDeltaField.getAttribute("objects").equals("")) {
258 if (eBaseField.getAttribute("objects").trim().length() == 0) {
259 eBaseField.setAttribute("objects", eDeltaField
260 .getAttribute("objects"));
261 } else {
262 String data = (eBaseField.getAttribute("objects") + " " + eDeltaField
263 .getAttribute("objects"));
264 Set<String> set = new HashSet<String>(Arrays.asList(data
265 .split("\\s+")));
266 StringBuffer result = new StringBuffer();
267 for (String s : set) {
268 result.append(" ").append(s.trim());
269 }
270 eBaseField.setAttribute("objects", result.substring(1));
271 }
272 }
273 // attribute: value (separated by "|")
274 if (!eDeltaField.getAttribute("value").equals("")) {
275 if (eBaseField.getAttribute("value").trim().length() == 0) {
276 eBaseField.setAttribute("value", eDeltaField
277 .getAttribute("value"));
278 } else {
279 String data = (eBaseField.getAttribute("value") + " | " + eDeltaField
280 .getAttribute("value"));
281 Set<String> set = new HashSet<String>(Arrays.asList(data
282 .split("\\s*\\|\\s*")));
283 StringBuffer result = new StringBuffer();
284 for (String s : set) {
285 result.append(" | ").append(s.trim());
286 }
287 eBaseField.setAttribute("value", result.substring(3));
288 }
289 }
290 // attribute: xpath (separated by "|")
291 if (!eDeltaField.getAttribute("xpath").equals("")) {
292 if (eBaseField.getAttribute("xpath").trim().length() == 0) {
293 eBaseField.setAttribute("xpath", eDeltaField
294 .getAttribute("xpath"));
295 } else {
296 String data = (eBaseField.getAttribute("xpath") + " | " + eDeltaField
297 .getAttribute("xpath"));
298 Set<String> set = new HashSet<String>(Arrays.asList(data
299 .split("\\s*\\|\\s*")));
300 StringBuffer result = new StringBuffer();
301 for (String s : set) {
302 result.append(" | ").append(s.trim());
303 }
304 eBaseField.setAttribute("xpath", result.substring(3));
305 }
306 }
307
308 // attributes: sortable, classification, i18n (will be overwritten)
309 if (!eDeltaField.getAttribute("sortable").equals("")) {
310 eBaseField.setAttribute("sortable", eDeltaField
311 .getAttribute("sortable"));
312 }
313 if (!eDeltaField.getAttribute("i18n").equals("")) {
314 eBaseField.setAttribute("i18n", eDeltaField.getAttribute("i18n"));
315 }
316 if (!eDeltaField.getAttribute("classification").equals("")) {
317 eBaseField.setAttribute("classification", eDeltaField
318 .getAttribute("classification"));
319 }
320 }
321
322 private void overwriteField(Element eBaseField, Element eDeltaField) {
323 Node newField = eBaseField.getOwnerDocument().importNode(eDeltaField,
324 true);
325 eBaseField.getParentNode().replaceChild(newField, eBaseField);
326 }
327 }