001: /*
002: * This file is part of PFIXCORE.
003: *
004: * PFIXCORE is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU Lesser General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * PFIXCORE is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public License
015: * along with PFIXCORE; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: */
019: package de.schlund.pfixcore.util;
020:
021: import java.io.File;
022: import java.io.IOException;
023: import java.util.Iterator;
024: import java.util.List;
025:
026: import javax.xml.transform.TransformerException;
027:
028: import org.w3c.dom.Document;
029: import org.w3c.dom.Element;
030: import org.w3c.dom.Node;
031: import org.xml.sax.SAXException;
032:
033: import de.schlund.pfixxml.util.Generics;
034: import de.schlund.pfixxml.util.XPath;
035: import de.schlund.pfixxml.util.Xml;
036:
037: public class Merge {
038:
039: public static void main(String[] args) throws Exception {
040: if (args.length != 3) {
041: throw new IOException("expected 3 arguments, got "
042: + args.length);
043: }
044: new Merge(new File(args[0]), args[1], new File(args[2])).run();
045: }
046:
047: //--
048:
049: private final File src;
050: private final String srcPath;
051: private final File dest;
052: private final boolean verbose;
053:
054: public Merge(File src, String srcPath, File dest) {
055: this (src, srcPath, dest, true);
056: }
057:
058: public Merge(File src, String srcPath, File dest, boolean verbose) {
059: this .src = src;
060: this .srcPath = srcPath;
061: this .dest = dest;
062: this .verbose = verbose;
063: }
064:
065: public void run() throws SAXException, IOException,
066: TransformerException {
067: Document destDoc;
068: List<Node> nodes;
069: int modified;
070:
071: if (verbose)
072: System.out.println("Merge " + src + " into" + dest);
073: destDoc = Xml.parseMutable(dest);
074: remove(XPath
075: .select(destDoc,
076: "/include_parts/part/theme[count(*) = 0 and normalize-space(text()) = '']"));
077: remove(XPath.select(destDoc,
078: "/include_parts/part[count(theme) = 0]"));
079: nodes = XPath.select(Xml.parseMutable(src), srcPath);
080: modified = merge(Generics.<Element> convertList(nodes), destDoc);
081: if (verbose)
082: System.out.println(" merged: " + modified);
083: Xml.serialize(destDoc, dest, true, true);
084: }
085:
086: private int merge(List<Element> src, Document dest)
087: throws TransformerException {
088: int merged;
089:
090: merged = 0;
091: for (Element element : src) {
092: if (mergeTheme(element, dest)) {
093: merged++;
094: }
095: }
096: return merged;
097: }
098:
099: private boolean mergeTheme(Element src, Document dest)
100: throws TransformerException {
101: Element part;
102:
103: ensureElement(src, "theme");
104: part = (Element) src.getParentNode();
105: ensureElement(part, "part");
106: return mergeTheme(getName(part), getName(src), src, dest);
107: }
108:
109: private boolean mergeTheme(String partName, String themeName,
110: Element src, Document dest) throws TransformerException {
111: Node all;
112: Element destPart;
113: Element destTheme;
114: Node first;
115:
116: all = XPath.selectNode(dest, "/include_parts");
117: destPart = getOrCreate(all, "part", partName);
118: destTheme = get(destPart, "theme", themeName);
119: if (destTheme != null) {
120: return false;
121: }
122: destTheme = (Element) dest.importNode(src, true);
123: first = destPart.getFirstChild();
124: if (first != null) {
125: destPart.insertBefore(destTheme, first);
126: } else {
127: destPart.appendChild(destTheme);
128: }
129: return true;
130: }
131:
132: private void ensureElement(Element ele, String name) {
133: if (!name.equals(ele.getTagName())) {
134: throw new IllegalArgumentException(
135: "illegal element: expected " + name + ", found "
136: + ele.getTagName());
137: }
138: }
139:
140: private Element getOrCreate(Node root, String element, String name)
141: throws TransformerException {
142: Element result;
143:
144: result = (Element) XPath.selectNode(root, element
145: + "[@name = '" + name + "']");
146: if (result == null) {
147: result = root.getOwnerDocument().createElement(element);
148: result.setAttribute("name", name);
149: root.appendChild(result);
150: }
151: return result;
152: }
153:
154: private Element get(Node root, String element, String name)
155: throws TransformerException {
156: Element result;
157:
158: result = (Element) XPath.selectNode(root, element
159: + "[@name = '" + name + "']");
160: return result;
161: }
162:
163: private static String getName(Element ele)
164: throws TransformerException {
165: String name;
166:
167: name = ele.getAttribute("name");
168: if (name == null) {
169: throw new TransformerException("missing name: "
170: + Xml.serialize(ele, true, false));
171: }
172: return name;
173: }
174:
175: private void remove(List<Node> nodes) {
176: Iterator<Node> iter;
177: Node node;
178:
179: iter = nodes.iterator();
180: while (iter.hasNext()) {
181: node = (Node) iter.next();
182: node.getParentNode().removeChild(node);
183: }
184: }
185: }
|