1
2
3
4
5
6
7 package org.asyrinx.joey.gen.ant.task;
8
9 import java.io.File;
10 import java.io.OutputStream;
11 import java.io.PrintWriter;
12 import java.util.ArrayList;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Map;
16
17 import org.apache.commons.logging.Log;
18 import org.apache.commons.logging.LogFactory;
19 import org.apache.tools.ant.BuildException;
20 import org.apache.tools.ant.Task;
21 import org.apache.tools.ant.types.FileSet;
22 import org.asyrinx.brownie.core.lang.ObjectUtils;
23 import org.asyrinx.brownie.core.lang.StringUtils;
24 import org.asyrinx.joey.gen.ant.ModelLoader;
25 import org.asyrinx.joey.gen.command.rdb.StandardCommands;
26 import org.asyrinx.joey.gen.core.impl.S2ContainerLoader;
27 import org.asyrinx.joey.gen.model.Element;
28 import org.asyrinx.joey.gen.model.ElementSet;
29 import org.asyrinx.joey.gen.model.EnumerationEntry;
30 import org.asyrinx.joey.gen.model.command.Command;
31 import org.asyrinx.joey.gen.model.rdb.Column;
32 import org.asyrinx.joey.gen.model.rdb.Database;
33 import org.asyrinx.joey.gen.model.rdb.Databases;
34 import org.asyrinx.joey.gen.model.rdb.ForeignKey;
35 import org.asyrinx.joey.gen.model.rdb.ForeignKeyEntry;
36 import org.asyrinx.joey.gen.model.rdb.Index;
37 import org.asyrinx.joey.gen.model.rdb.IndexEntry;
38 import org.asyrinx.joey.gen.model.rdb.RdbEnumeration;
39 import org.asyrinx.joey.gen.model.rdb.Table;
40 import org.asyrinx.joey.gen.model.rdb.TablePattern;
41 import org.asyrinx.joey.gen.model.rdb.TablePatternParam;
42 import org.seasar.framework.container.S2Container;
43
44 /***
45 * @author takeshi
46 */
47 public class JoeyModificationTask extends Task {
48
49 protected final Log log = LogFactory.getLog(this.getClass());
50
51 protected List filesets = new ArrayList();
52
53 public void addFileset(FileSet set) {
54 filesets.add(set);
55 }
56
57 private S2Container container = S2ContainerLoader.getContainer();
58
59 public void execute() throws BuildException {
60 final ModelLoader modelLoader = (ModelLoader) container.getComponent(ModelLoader.class);
61 try {
62 final Databases currentModel = modelLoader.loadDatabaseModels(filesets, this.project);
63 final Databases lastModel = modelLoader.loadDatabaseModels(getLastSchemaFileSets(), this.project);
64
65 final Command dbCommand = new StandardCommands();
66 dbCommand.execute(currentModel);
67 dbCommand.execute(lastModel);
68
69 final ShowModification showModification = new ShowModification(this.isShowNoChange(), this.isShowDeleted(),
70 this.isShowAppended());
71 showModification.execute(currentModel, lastModel);
72 } catch (Exception e) {
73 throw new BuildException(e);
74 }
75 }
76
77 private List getLastSchemaFileSets() {
78 final List result = new ArrayList();
79 final FileSet fs = new FileSet();
80 fs.setDir(this.getLastSchemaDir());
81 fs.setIncludes("*");
82 result.add(fs);
83 return result;
84 }
85
86 private File lastSchemaDir = null;
87
88 public File getLastSchemaDir() {
89 return lastSchemaDir;
90 }
91
92 public void setLastSchemaDir(File lastSchemaDir) {
93 this.lastSchemaDir = lastSchemaDir;
94 }
95
96 private boolean showNoChange = true;
97
98 private boolean showDeleted = true;
99
100 private boolean showAppended = true;
101
102 public boolean isShowAppended() {
103 return showAppended;
104 }
105
106 public void setShowAppended(boolean showAppended) {
107 this.showAppended = showAppended;
108 }
109
110 public boolean isShowDeleted() {
111 return showDeleted;
112 }
113
114 public void setShowDeleted(boolean showDeleted) {
115 this.showDeleted = showDeleted;
116 }
117
118 public boolean isShowNoChange() {
119 return showNoChange;
120 }
121
122 public void setShowNoChange(boolean showNoChange) {
123 this.showNoChange = showNoChange;
124 }
125 }
126
127 interface ModificationView {
128 void show(Element current, Element last);
129 }
130
131 class ShowModification {
132
133 public ShowModification(boolean showNoChange, boolean showDeleted, boolean showAppended) {
134 super();
135 this.showNoChange = showNoChange;
136 this.showDeleted = showDeleted;
137 this.showAppended = showAppended;
138 }
139
140 private final boolean showNoChange;
141
142 private final boolean showDeleted;
143
144 private final boolean showAppended;
145
146
147
148 private PrintWriter writer = getWriter(getOutputStream());
149
150 /***
151 * @param currentModel
152 * @param lastModel
153 */
154 public void execute(Databases currentModel, Databases lastModel) {
155 databasesView.show(currentModel, lastModel);
156 }
157
158 interface ShowClosure {
159 void invoke(ModificationView view, String header, final Element lastElement, final Element currElement);
160 }
161
162 final ShowClosure lastBaseClosure = new ShowClosure() {
163 public void invoke(ModificationView view, String header, final Element lastElement, final Element currElement) {
164 if (currElement == null) {
165 if (isShowDeleted())
166 printElementName("-", header, lastElement);
167 } else if (currElement.equals(lastElement)) {
168 if (isShowNoChange())
169 printElementName(" ", header, lastElement);
170 if (view != null)
171 view.show(currElement, lastElement);
172 } else {
173 printElementName("!", header, lastElement);
174 if (view != null)
175 view.show(currElement, lastElement);
176 }
177 }
178 };
179
180 final ShowClosure currentBaseClosure = new ShowClosure() {
181 public void invoke(ModificationView view, String header, final Element lastElement, final Element currElement) {
182 if (lastElement == null) {
183 if (isShowAppended())
184 printElementName("+", header, currElement);
185 }
186 }
187 };
188
189 protected void showModification(ModificationView view, String header, ElementSet current, ElementSet last) {
190 if (ObjectUtils.equals(current, last)) {
191 if (!isShowNoChange())
192 return;
193 }
194 if (current.careChildOrder())
195 showModificationByOrder(view, header, current, last);
196 else
197 showModificationByName(view, header, current, last);
198 }
199
200 protected void showModificationByOrder(ModificationView view, String header, ElementSet current, ElementSet last) {
201 for (int i = 0; i < last.size(); i++) {
202 final Element lastElement = last.getElement(i);
203 final Element currElement = current.getElement(i);
204 lastBaseClosure.invoke(view, header, lastElement, currElement);
205 }
206 if (last.size() >= current.size())
207 return;
208 for (int i = last.size(); i < current.size(); i++) {
209 final Element lastElement = null;
210 final Element currElement = current.getElement(i);
211 currentBaseClosure.invoke(view, header, lastElement, currElement);
212 }
213 }
214
215 protected void showModificationByName(ModificationView view, String header, ElementSet current, ElementSet last) {
216 for (Iterator i = last.iterator(); i.hasNext();) {
217 final Element lastElement = (Element) i.next();
218 final Element currElement = current.getElement(lastElement.getName());
219 lastBaseClosure.invoke(view, header, lastElement, currElement);
220 }
221 for (Iterator i = current.iterator(); i.hasNext();) {
222 final Element currElement = (Element) i.next();
223 final Element lastElement = last.getElement(currElement.getName());
224 currentBaseClosure.invoke(view, header, lastElement, currElement);
225 }
226 }
227
228 void printElementName(String mark, String header, Element element) {
229 if (element != null) {
230 writer.println(mark + " "
231 + StringUtils.repeat(" ", (element.getAncestorDepth() - 1) * 4)
232 + StringUtils.padTail(header, " ", 12)
233 + " : " + element.getName());
234 } else {
235 writer.println(mark + " "
236 + StringUtils.repeat(" ", 12)
237 + StringUtils.padTail(header, " ", 12)
238 + " : " + "null");
239 }
240 }
241
242 void printPropLine(Element element, String name, boolean last, boolean current) {
243 printPropLine(element, name, new Boolean(last), new Boolean(current));
244 }
245
246 void printPropLine(Element element, String name, Object last, Object current) {
247 final int indent = element.getAncestorDepth() * 4;
248 if ((last instanceof Map) && (current instanceof Map)) {
249 printPropLineAsMap(indent + 4, name, (Map) last, (Map) current);
250 } else {
251 printPropLine(indent, name, last, current);
252 }
253 }
254
255 void printPropLine(int indent, String name, Object last, Object current) {
256 if (ObjectUtils.equals(last, current)) {
257 if (!isShowNoChange())
258 return;
259 writer.println(" " + " "
260 + StringUtils.repeat(" ", indent)
261 + name + " : " + last);
262 } else {
263 writer.println("!" + " "
264 + StringUtils.repeat(" ", indent)
265 + name + " : [" + last + "] -> [" + current + "]");
266 }
267 }
268
269 void printPropLineAsMap(int indent, String name, Map last, Map current) {
270 if (ObjectUtils.equals(last, current)) {
271 if (!isShowNoChange())
272 return;
273 writer.println(" " + " "
274 + StringUtils.repeat(" ", indent)
275 + name + " : ");
276 } else {
277 writer.println("!" + " "
278 + StringUtils.repeat(" ", indent)
279 + name + " : ");
280 }
281 for (Iterator i = last.keySet().iterator(); i.hasNext();) {
282 final Object key = i.next();
283 final Object lastValue = last.get(key);
284 final Object currValue = current.get(key);
285 printPropLine(indent + 4, key.toString(), lastValue, currValue);
286 }
287 for (Iterator i = current.keySet().iterator(); i.hasNext();) {
288 final Object key = i.next();
289 if (last.containsKey(key)) {
290
291 continue;
292 }
293 final Object lastValue = last.get(key);
294 final Object currValue = current.get(key);
295 printPropLine(indent + 4, key.toString(), lastValue, currValue);
296 }
297 }
298
299 final ModificationView databasesView = new ModificationView() {
300 public void show(Element current, Element last) {
301 final Databases c = (Databases) current;
302 final Databases l = (Databases) last;
303 printPropLine(c, "options", l.getOptions(), c.getOptions());
304 showModification(databaseView, "database", c.getDatabases(), l.getDatabases());
305 }
306 };
307
308 final ModificationView databaseView = new ModificationView() {
309 public void show(Element current, Element last) {
310 final Database c = (Database) current;
311 final Database l = (Database) last;
312 printPropLine(c, "options", l.getOptions(), c.getOptions());
313 showModification(enumView, "enum", c.getEnumerations(), l.getEnumerations());
314 showModification(tableView, "table", c.getTables(), l.getTables());
315 }
316 };
317
318 final ModificationView enumView = new ModificationView() {
319 public void show(Element current, Element last) {
320 final RdbEnumeration c = (RdbEnumeration) current;
321 final RdbEnumeration l = (RdbEnumeration) last;
322 printPropLine(c, "options", l.getOptions(), c.getOptions());
323 showModification(enumEntryView, "enum-entry", c, l);
324 }
325 };
326
327 final ModificationView enumEntryView = new ModificationView() {
328 public void show(Element current, Element last) {
329 final EnumerationEntry c = (EnumerationEntry) current;
330 final EnumerationEntry l = (EnumerationEntry) last;
331 printPropLine(c, "value", l.getValue(), c.getValue());
332 printPropLine(c, "options", l.getOptions(), c.getOptions());
333 }
334 };
335
336 final ModificationView tableView = new ModificationView() {
337 public void show(Element current, Element last) {
338 final Table c = (Table) current;
339 final Table l = (Table) last;
340 printPropLine(c, "extends", l.getExtends(), c.getExtends());
341 printPropLine(c, "captionColumn", l.getCaptionColumn(), c.getCaptionColumn());
342 printPropLine(c, "options", l.getOptions(), c.getOptions());
343 showModification(columnView, "column", c.getColumns(), l.getColumns());
344 showModification(fkView, "foreignKey", c.getForeignKeys(), l.getForeignKeys());
345 showModification(indexView, "index", c.getIndexes(), l.getIndexes());
346 showModification(patternView, "pattern", c.getPatterns(), l.getPatterns());
347 }
348 };
349
350 final ModificationView columnView = new ModificationView() {
351 public void show(Element current, Element last) {
352 final Column c = (Column) current;
353 final Column l = (Column) last;
354 printPropLine(c, "type", l.getType(), c.getType());
355 printPropLine(c, "size", l.getSize(), c.getSize());
356 printPropLine(c, "required", l.isRequired(), c.isRequired());
357 printPropLine(c, "primaryKey", l.isPrimaryKey(), c.isPrimaryKey());
358 printPropLine(c, "defaultValue", l.getDefaultValue(), c.getDefaultValue());
359 printPropLine(c, "enum", l.getEnum(), c.getEnum());
360 printPropLine(c, "options", l.getOptions(), c.getOptions());
361 }
362 };
363
364 final ModificationView fkView = new ModificationView() {
365 public void show(Element current, Element last) {
366 final ForeignKey c = (ForeignKey) current;
367 final ForeignKey l = (ForeignKey) last;
368 printPropLine(c, "foreign", l.getForeign(), c.getForeign());
369 printPropLine(c, "type", l.getType(), c.getType());
370 printPropLine(c, "cascade", l.getCascade(), c.getCascade());
371 printPropLine(c, "options", l.getOptions(), c.getOptions());
372 showModification(fkEntryView, "reference", c, l);
373 }
374 };
375
376 final ModificationView fkEntryView = new ModificationView() {
377 public void show(Element current, Element last) {
378 final ForeignKeyEntry c = (ForeignKeyEntry) current;
379 final ForeignKeyEntry l = (ForeignKeyEntry) last;
380 printPropLine(c, "local", l.getLocal(), c.getLocal());
381 printPropLine(c, "foreign", l.getForeign(), c.getForeign());
382 printPropLine(c, "options", l.getOptions(), c.getOptions());
383 }
384 };
385
386 final ModificationView indexView = new ModificationView() {
387 public void show(Element current, Element last) {
388 final Index c = (Index) current;
389 final Index l = (Index) last;
390 printPropLine(c, "unique", l.isUnique(), c.isUnique());
391 printPropLine(c, "options", l.getOptions(), c.getOptions());
392 showModification(indexEntryView, "index-column", c, l);
393 }
394 };
395
396 final ModificationView uniqueView = new ModificationView() {
397 public void show(Element current, Element last) {
398 final Index c = (Index) current;
399 final Index l = (Index) last;
400 printPropLine(c, "unique", l.isUnique(), c.isUnique());
401 printPropLine(c, "options", l.getOptions(), c.getOptions());
402 showModification(indexEntryView, "unique-column", c, l);
403 }
404 };
405
406 final ModificationView indexEntryView = new ModificationView() {
407 public void show(Element current, Element last) {
408 final IndexEntry c = (IndexEntry) current;
409 final IndexEntry l = (IndexEntry) last;
410 printPropLine(c, "options", l.getOptions(), c.getOptions());
411 }
412 };
413
414 final ModificationView patternView = new ModificationView() {
415 public void show(Element current, Element last) {
416 final TablePattern c = (TablePattern) current;
417 final TablePattern l = (TablePattern) last;
418 printPropLine(c, "options", l.getOptions(), c.getOptions());
419 showModification(patternParamView, "param", c, l);
420 }
421 };
422
423 final ModificationView patternParamView = new ModificationView() {
424 public void show(Element current, Element last) {
425 final TablePatternParam c = (TablePatternParam) current;
426 final TablePatternParam l = (TablePatternParam) last;
427 printPropLine(c, "value", l.getValue(), c.getValue());
428 printPropLine(c, "options", l.getOptions(), c.getOptions());
429 }
430 };
431
432 protected OutputStream getOutputStream() {
433 return System.out;
434 }
435
436 protected PrintWriter getWriter(OutputStream stream) {
437 return new PrintWriter(stream) {
438 public void println(String x) {
439 System.out.println(x);
440
441 }
442 };
443 }
444
445 public boolean isShowAppended() {
446 return showAppended;
447 }
448
449 public boolean isShowDeleted() {
450 return showDeleted;
451 }
452
453 public boolean isShowNoChange() {
454 return showNoChange;
455 }
456 }