001: /*
002: * transformica 2
003: * Code generator
004: * Copyright (C) 2004 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.pavelvlasov.com/pv/content/menu.show@id=products.transformica.html
021: * e-Mail: support@hammurapi.biz
022: */
023: package biz.hammurapi.transformica;
024:
025: import java.util.Collection;
026: import java.util.HashMap;
027: import java.util.Iterator;
028: import java.util.LinkedList;
029: import java.util.List;
030: import java.util.Map;
031: import java.util.Properties;
032:
033: import org.apache.tools.ant.BuildException;
034: import org.apache.tools.ant.Project;
035: import org.apache.tools.ant.Task;
036: import org.apache.velocity.app.Velocity;
037:
038: import biz.hammurapi.ant.Param;
039: import biz.hammurapi.util.CompositeVisitor;
040: import biz.hammurapi.util.Visitable;
041:
042: /**
043: * @ant.element name="Transformica"
044: * @author Pavel Vlasov
045: */
046: public class TransformTask extends Task {
047: public static final String SESSION = "session";
048: protected List channels = new LinkedList();
049: private List templateDirs = new LinkedList();
050: protected TransformSession session = new TransformSession(this );
051: private ModelEntry modelEntry;
052:
053: /**
054: * Defines transformation channel.
055: * @ant.required
056: * @return
057: */
058: public Channel createChannel() {
059: Channel ret = new Channel(session);
060: channels.add(ret);
061: return ret;
062: }
063:
064: /**
065: * Model. Must implement biz.hammurapi.util.Visitable
066: * @ant.required
067: * @return
068: */
069: public ModelEntry createModel() throws BuildException {
070: if (modelEntry == null) {
071: modelEntry = new ModelEntry();
072: return modelEntry;
073: } else {
074: throw new BuildException("Model already created");
075: }
076: }
077:
078: protected Visitable getModel(TransformSession session)
079: throws BuildException {
080: if (modelEntry == null) {
081: throw new BuildException("Model is no set");
082: } else {
083: return (Visitable) modelEntry.getObject(null);
084: }
085: }
086:
087: /**
088: * Templates directory
089: * @ant.required
090: * @return
091: */
092: public TemplateDir createTemplateDir() {
093: TemplateDir ret = new TemplateDir();
094: templateDirs.add(ret);
095: return ret;
096: }
097:
098: /* (non-Javadoc)
099: * @see org.apache.tools.ant.Task#execute()
100: */
101: public void execute() throws BuildException {
102: session.reset();
103:
104: try {
105: if (templateDirs.isEmpty()) {
106: Velocity.init(engineProperties);
107: } else {
108: StringBuffer dirList = new StringBuffer();
109: Iterator it = templateDirs.iterator();
110: while (it.hasNext()) {
111: TemplateDir td = (TemplateDir) it.next();
112: String dirPath = td.getDir().getAbsolutePath();
113: log("Template dir: " + dirPath, Project.MSG_VERBOSE);
114: dirList.append(dirPath);
115: if (it.hasNext()) {
116: dirList.append(",");
117: }
118: }
119: Properties velocityProperties = new Properties(
120: engineProperties);
121: velocityProperties
122: .setProperty("file.resource.loader.path",
123: dirList.toString());
124: Velocity.init(velocityProperties);
125: }
126:
127: if (touchDetector != null) {
128: touchDetector.init();
129: }
130:
131: Iterator it = contextEntries.values().iterator();
132: while (it.hasNext()) {
133: Object o = it.next();
134: if (o instanceof ContextObject) {
135: ((ContextObject) o).init(session);
136: }
137: }
138:
139: Collection visibleChannels = new LinkedList();
140: it = channels.iterator();
141: while (it.hasNext()) {
142: Channel ch = (Channel) it.next();
143: ch.init();
144: if (ch.getName() != null) {
145: if (channelMap.containsKey(ch.getName())) {
146: throw new BuildException(
147: "Duplicate channel name: "
148: + ch.getName());
149: }
150: channelMap.put(ch.getName(), ch);
151: }
152:
153: if (!ch.isHidden()) {
154: visibleChannels.add(ch);
155: }
156: }
157:
158: Visitable model = getModel(session);
159: session.setRoot(model);
160:
161: CompositeVisitor cv = new CompositeVisitor(visibleChannels);
162: model.accept(cv);
163:
164: if (touchDetector != null) {
165: touchDetector.destroy();
166: }
167:
168: it = contextEntries.values().iterator();
169: while (it.hasNext()) {
170: Object o = it.next();
171: if (o instanceof ContextObject) {
172: ((ContextObject) o).destroy();
173: }
174: }
175:
176: while (it.hasNext()) {
177: Channel ch = (Channel) it.next();
178: ch.destroy();
179: }
180: } catch (Exception e) {
181: throw new BuildException(e);
182: }
183: }
184:
185: /**
186: * @return
187: */
188: List getChannels() {
189: return channels;
190: }
191:
192: private Map contextEntries = new HashMap();
193:
194: public Map getContextEntries() {
195: return contextEntries;
196: }
197:
198: /**
199: * Context entry which will be available in templates
200: * @ant.non-required
201: * @param param
202: * @throws BuildException
203: */
204: public void addConfiguredContextEntry(ContextObjectEntry entry)
205: throws BuildException {
206: if (entry.getName() == null) {
207: throw new BuildException("Context entry name is null");
208: }
209: Channel.validateEntryName(entry.getName());
210: contextEntries.put(entry.getName(), entry.getObject(null));
211: }
212:
213: protected LinkedList acceptors = new LinkedList();
214:
215: /**
216: * Model element acceptor.
217: * @ant.non-required
218: * @param param
219: * @throws BuildException
220: */
221: public void addConfiguredAcceptor(AcceptorEntry entry)
222: throws BuildException {
223: acceptors.add(entry.getObject(null));
224: }
225:
226: private Properties engineProperties = new Properties();
227:
228: public Properties engineProperties() {
229: return engineProperties;
230: }
231:
232: /**
233: * Velocity configuration property
234: * @ant.non-required
235: * @param param
236: * @throws BuildException
237: */
238: public void addConfiguredEngineProperty(Param param)
239: throws BuildException {
240: if (param.getName() == null) {
241: throw new BuildException("Engine property name is null");
242: }
243:
244: if (param.getObject(null) == null) {
245: throw new BuildException("Engine property value is null");
246: }
247:
248: engineProperties.setProperty(param.getName(), param.getObject(
249: null).toString());
250: }
251:
252: private TouchDetector touchDetector;
253: private Map channelMap = new HashMap();
254:
255: TouchDetector getTouchDetector() {
256: return touchDetector;
257: }
258:
259: /**
260: * File info file.
261: * @ant.non-required.
262: * @param ftsrf
263: * @throws BuildException
264: */
265: public void addConfiguredFileTouchDetector(
266: FileTouchDetectorFactory ftsrf) throws BuildException {
267: if (touchDetector != null) {
268: throw new BuildException("TimeStamp repository already set");
269: }
270: touchDetector = ftsrf.newTimeStampRepo();
271: }
272:
273: /**
274: * JDBC file info repository.
275: * @ant.non-required
276: * @param jtsrf
277: * @throws BuildException
278: */
279: public void addConfiguredJdbcTouchDetector(
280: HypersonicTouchDetectorFactory jtsrf) throws BuildException {
281: if (touchDetector != null) {
282: throw new BuildException("TimeStamp repository already set");
283: }
284: touchDetector = jtsrf.newTimeStampRepo();
285: }
286:
287: /**
288: * @param channelName
289: * @return
290: */
291: public Channel lookupChannel(String channelName) {
292: return (Channel) channelMap.get(channelName);
293: }
294: }
|