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