001: /* ***** BEGIN LICENSE BLOCK *****
002: * Version: MPL 1.1
003: * The contents of this file are subject to the Mozilla Public License Version
004: * 1.1 (the "License"); you may not use this file except in compliance with
005: * the License. You may obtain a copy of the License at
006: * http://www.mozilla.org/MPL/
007: *
008: * Software distributed under the License is distributed on an "AS IS" basis,
009: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
010: * for the specific language governing rights and limitations under the
011: * License.
012: *
013: * The Original Code is Riot.
014: *
015: * The Initial Developer of the Original Code is
016: * Neteye GmbH.
017: * Portions created by the Initial Developer are Copyright (C) 2006
018: * the Initial Developer. All Rights Reserved.
019: *
020: * Contributor(s):
021: * Felix Gnass [fgnass at neteye dot de]
022: *
023: * ***** END LICENSE BLOCK ***** */
024: package org.riotfamily.revolt.config;
025:
026: import java.util.ArrayList;
027: import java.util.Iterator;
028: import java.util.List;
029:
030: import org.riotfamily.revolt.ChangeSet;
031: import org.riotfamily.revolt.EvolutionHistory;
032: import org.riotfamily.revolt.Refactoring;
033: import org.riotfamily.revolt.definition.Column;
034: import org.riotfamily.revolt.definition.ForeignKey;
035: import org.riotfamily.revolt.definition.Index;
036: import org.riotfamily.revolt.definition.RecordEntry;
037: import org.riotfamily.revolt.definition.Reference;
038: import org.riotfamily.revolt.definition.UniqueConstraint;
039: import org.riotfamily.revolt.definition.UpdateStatement;
040: import org.riotfamily.revolt.refactor.AddColumn;
041: import org.riotfamily.revolt.refactor.AddForeignKey;
042: import org.riotfamily.revolt.refactor.AddUniqueConstraint;
043: import org.riotfamily.revolt.refactor.CreateAutoIncrementSequence;
044: import org.riotfamily.revolt.refactor.CreateIndex;
045: import org.riotfamily.revolt.refactor.CreateTable;
046: import org.riotfamily.revolt.refactor.DropColumn;
047: import org.riotfamily.revolt.refactor.DropForeignKey;
048: import org.riotfamily.revolt.refactor.DropIndex;
049: import org.riotfamily.revolt.refactor.DropTable;
050: import org.riotfamily.revolt.refactor.DropUniqueConstraint;
051: import org.riotfamily.revolt.refactor.InsertData;
052: import org.riotfamily.revolt.refactor.ModifyColumn;
053: import org.riotfamily.revolt.refactor.RenameColumn;
054: import org.riotfamily.revolt.refactor.RenameTable;
055: import org.riotfamily.revolt.refactor.UpdateData;
056: import org.springframework.beans.MutablePropertyValues;
057: import org.springframework.beans.factory.config.BeanDefinition;
058: import org.springframework.beans.factory.config.BeanDefinitionHolder;
059: import org.springframework.beans.factory.config.ConstructorArgumentValues;
060: import org.springframework.beans.factory.config.RuntimeBeanReference;
061: import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
062: import org.springframework.beans.factory.support.RootBeanDefinition;
063: import org.springframework.beans.factory.xml.NamespaceHandler;
064: import org.springframework.beans.factory.xml.ParserContext;
065: import org.springframework.util.StringUtils;
066: import org.springframework.util.xml.DomUtils;
067: import org.w3c.dom.Element;
068: import org.w3c.dom.Node;
069: import org.w3c.dom.NodeList;
070:
071: /**
072: * NamespaceHandler that handles the <code>revolt</code>
073: * namspace as defined in <code>revolt.xsd</code> which can be found in
074: * the same package.
075: */
076: public class RevoltNamespaceHandler implements NamespaceHandler {
077:
078: public void init() {
079: }
080:
081: public BeanDefinition parse(Element element,
082: ParserContext parserContext) {
083: if (DomUtils.nodeNameEquals(element, "history")) {
084: RootBeanDefinition definition = new RootBeanDefinition();
085: definition.setBeanClass(EvolutionHistory.class);
086:
087: ConstructorArgumentValues ctorArgs = new ConstructorArgumentValues();
088: ctorArgs.addGenericArgumentValue(new RuntimeBeanReference(
089: element.getAttribute("data-source")));
090:
091: definition.setConstructorArgumentValues(ctorArgs);
092: MutablePropertyValues pv = new MutablePropertyValues();
093: pv.addPropertyValue("changeSets", parseChangeSets(element));
094: definition.setPropertyValues(pv);
095: BeanDefinitionHolder holder = new BeanDefinitionHolder(
096: definition, element.getAttribute("module"));
097: BeanDefinitionReaderUtils.registerBeanDefinition(holder,
098: parserContext.getRegistry());
099: return definition;
100: }
101: throw new IllegalArgumentException(
102: "Expected <history> but found: "
103: + element.getNodeName());
104: }
105:
106: private List parseChangeSets(Element element) {
107: ArrayList changeSets = new ArrayList();
108: Iterator it = DomUtils.getChildElementsByTagName(element,
109: "change-set").iterator();
110: while (it.hasNext()) {
111: Element ele = (Element) it.next();
112: changeSets.add(new ChangeSet(ele.getAttribute("id"),
113: parseRefactorings(ele)));
114: }
115: return changeSets;
116: }
117:
118: private List parseRefactorings(Element element) {
119: ArrayList refactorings = new ArrayList();
120: NodeList childNodes = element.getChildNodes();
121:
122: for (int i = 0; i < childNodes.getLength(); i++) {
123: Node child = childNodes.item(i);
124: if (child instanceof Element) {
125: Refactoring refactoring = parseRefactoring((Element) child);
126: if (refactoring != null) {
127: refactorings.add(refactoring);
128: }
129: }
130: }
131: return refactorings;
132: }
133:
134: private Refactoring parseRefactoring(Element ele) {
135: Refactoring refactoring = null;
136: if (DomUtils.nodeNameEquals(ele, "add-column")) {
137: refactoring = new AddColumn(ele.getAttribute("table"),
138: parseColumn(ele));
139: }
140: if (DomUtils.nodeNameEquals(ele, "add-foreign-key")) {
141: refactoring = new AddForeignKey(ele.getAttribute("table"),
142: new ForeignKey(ele.getAttribute("name"), ele
143: .getAttribute("references"),
144: parseReferences(ele), parseOnDelete(ele),
145: parseOnUpdate(ele)));
146: }
147: if (DomUtils.nodeNameEquals(ele, "add-unique-constraint")) {
148: refactoring = new AddUniqueConstraint(ele
149: .getAttribute("table"),
150: new UniqueConstraint(ele.getAttribute("name"),
151: StringUtils.tokenizeToStringArray(ele
152: .getAttribute("on"), ",")));
153: }
154: if (DomUtils.nodeNameEquals(ele, "create-index")) {
155: refactoring = new CreateIndex(ele.getAttribute("table"),
156: new Index(ele.getAttribute("name"), StringUtils
157: .tokenizeToStringArray(ele
158: .getAttribute("on"), ","), Boolean
159: .valueOf(ele.getAttribute("unique"))
160: .booleanValue()));
161: }
162: if (DomUtils.nodeNameEquals(ele, "create-table")) {
163: refactoring = new CreateTable(ele.getAttribute("name"),
164: parseColumns(ele));
165: }
166: if (DomUtils.nodeNameEquals(ele, "drop-column")) {
167: refactoring = new DropColumn(ele.getAttribute("table"), ele
168: .getAttribute("column"));
169: }
170: if (DomUtils.nodeNameEquals(ele, "drop-foreign-key")) {
171: refactoring = new DropForeignKey(ele.getAttribute("table"),
172: ele.getAttribute("foreign-key"));
173: }
174: if (DomUtils.nodeNameEquals(ele, "drop-index")) {
175: refactoring = new DropIndex(ele.getAttribute("table"), ele
176: .getAttribute("index"));
177: }
178: if (DomUtils.nodeNameEquals(ele, "drop-table")) {
179: refactoring = new DropTable(ele.getAttribute("table"));
180: }
181: if (DomUtils.nodeNameEquals(ele, "drop-unique-constraint")) {
182: refactoring = new DropUniqueConstraint(ele
183: .getAttribute("table"), ele
184: .getAttribute("constraint"));
185: }
186: if (DomUtils.nodeNameEquals(ele, "modify-column")) {
187: refactoring = new ModifyColumn(ele.getAttribute("table"),
188: parseColumn(ele));
189: }
190: if (DomUtils.nodeNameEquals(ele, "rename-column")) {
191: refactoring = new RenameColumn(ele.getAttribute("table"),
192: ele.getAttribute("column"), ele
193: .getAttribute("rename-to"));
194: }
195: if (DomUtils.nodeNameEquals(ele, "rename-table")) {
196: refactoring = new RenameTable(ele.getAttribute("table"),
197: ele.getAttribute("rename-to"));
198: }
199: if (DomUtils.nodeNameEquals(ele, "insert-data")) {
200: refactoring = new InsertData(ele.getAttribute("table"),
201: parseEntries(ele));
202: }
203: if (DomUtils.nodeNameEquals(ele, "update-data")) {
204: refactoring = new UpdateData(parseUpdateStatements(ele));
205: }
206: if (DomUtils.nodeNameEquals(ele, "create-auto-increment-seq")) {
207: refactoring = new CreateAutoIncrementSequence(ele
208: .getAttribute("name"));
209: }
210: return refactoring;
211: }
212:
213: private String parseOnUpdate(Element ele) {
214: Element e = DomUtils.getChildElementByTagName(ele, "on-update");
215: return e != null ? e.getAttribute("value") : null;
216: }
217:
218: private String parseOnDelete(Element ele) {
219: Element e = DomUtils.getChildElementByTagName(ele, "on-delete");
220: return e != null ? e.getAttribute("value") : null;
221: }
222:
223: private List parseColumns(Element ele) {
224: ArrayList columns = new ArrayList();
225: Iterator it = DomUtils.getChildElementsByTagName(ele, "column")
226: .iterator();
227: while (it.hasNext()) {
228: columns.add(parseColumn((Element) it.next()));
229: }
230: return columns;
231: }
232:
233: private Column parseColumn(Element ele) {
234: Column column = new Column();
235: column.setName(ele.getAttribute("name"));
236: if (StringUtils.hasLength(ele.getAttribute("type"))) {
237: column.setType(ele.getAttribute("type"));
238: }
239: if (StringUtils.hasLength(ele.getAttribute("length"))) {
240: column.setLength(Integer
241: .valueOf(ele.getAttribute("length")).intValue());
242: }
243: if (StringUtils.hasLength(ele.getAttribute("primary-key"))) {
244: column.setPrimaryKey(Boolean.valueOf(
245: ele.getAttribute("primary-key")).booleanValue());
246: }
247: if (StringUtils.hasLength(ele.getAttribute("not-null"))) {
248: column.setNotNull(Boolean.valueOf(
249: ele.getAttribute("not-null")).booleanValue());
250: }
251: if (StringUtils.hasLength(ele.getAttribute("auto-increment"))) {
252: column.setAutoIncrement(Boolean.valueOf(
253: ele.getAttribute("auto-increment")).booleanValue());
254: }
255: if (StringUtils.hasLength(ele.getAttribute("default-value"))) {
256: column.setDefaultValue(ele.getAttribute("default-value"));
257: }
258: return column;
259: }
260:
261: private List parseReferences(Element ele) {
262: ArrayList references = new ArrayList();
263: Iterator it = DomUtils.getChildElementsByTagName(ele, "ref")
264: .iterator();
265: while (it.hasNext()) {
266: Element e = (Element) it.next();
267: references.add(new Reference(e.getAttribute("local"), e
268: .getAttribute("foreign")));
269: }
270: return references;
271: }
272:
273: private List parseEntries(Element ele) {
274: ArrayList entries = new ArrayList();
275: Iterator it = DomUtils.getChildElementsByTagName(ele, "entry")
276: .iterator();
277: while (it.hasNext()) {
278: Element e = (Element) it.next();
279: entries.add(new RecordEntry(e.getAttribute("column"), e
280: .getAttribute("value")));
281: }
282: return entries;
283: }
284:
285: private List parseUpdateStatements(Element ele) {
286: ArrayList statements = new ArrayList();
287: Iterator it = DomUtils.getChildElementsByTagName(ele,
288: "statement").iterator();
289: while (it.hasNext()) {
290: Element e = (Element) it.next();
291: statements.add(new UpdateStatement(e
292: .getAttribute("dialects"), e.getAttribute("sql")));
293: }
294: return statements;
295: }
296:
297: public BeanDefinitionHolder decorate(Node node,
298: BeanDefinitionHolder holder, ParserContext parserContext) {
299:
300: throw new UnsupportedOperationException(
301: "Bean decoration is not supported.");
302: }
303:
304: }
|