001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.openwire.tool;
018
019import java.io.File;
020import java.io.FileWriter;
021import java.io.PrintWriter;
022import java.util.ArrayList;
023import java.util.HashSet;
024import java.util.Iterator;
025import java.util.List;
026import java.util.Set;
027
028import org.apache.tools.ant.Project;
029import org.apache.tools.ant.taskdefs.FixCRLF;
030import org.codehaus.jam.JClass;
031import org.codehaus.jam.JProperty;
032import org.codehaus.jam.JamClassIterator;
033
034/**
035 * 
036 */
037public abstract class SingleSourceGenerator extends OpenWireGenerator {
038
039    protected Set<String> manuallyMaintainedClasses = new HashSet<String>();
040    protected File destFile;
041
042    protected JClass jclass;
043    protected JClass superclass;
044    protected String simpleName;
045    protected String className;
046    protected String baseClass;
047    protected List<JClass> sortedClasses;
048
049    public SingleSourceGenerator() {
050        initialiseManuallyMaintainedClasses();
051    }
052
053    public Object run() {
054
055        if (destFile == null) {
056            throw new IllegalArgumentException("No destFile defined!");
057        }
058        destFile.getParentFile().mkdirs();
059
060        PrintWriter out = null;
061        try {
062            out = new PrintWriter(new FileWriter(destFile));
063
064            ArrayList<JClass> classes = new ArrayList<JClass>();
065            JamClassIterator iter = getClasses();
066            while (iter.hasNext()) {
067                jclass = iter.nextClass();
068                if (isValidClass(jclass)) {
069                    classes.add(jclass);
070                }
071            }
072            sortedClasses = sort(classes);
073
074            generateSetup(out);
075            for (Iterator<JClass> iterator = sortedClasses.iterator(); iterator.hasNext();) {
076                jclass = iterator.next();
077                simpleName = jclass.getSimpleName();
078                superclass = jclass.getSuperclass();
079                className = getClassName(jclass);
080                baseClass = getBaseClassName(jclass);
081
082                System.out.println(getClass().getName() + " processing class: " + simpleName);
083                generateFile(out);
084            }
085            generateTearDown(out);
086
087        } catch (Exception e) {
088            throw new RuntimeException(e);
089        } finally {
090            if (out != null) {
091                out.close();
092            }
093        }
094
095        // Use the FixCRLF Ant Task to make sure the file has consistent
096        // newlines
097        // so that SVN does not complain on checkin.
098        Project project = new Project();
099        project.init();
100        FixCRLF fixCRLF = new FixCRLF();
101        fixCRLF.setProject(project);
102        fixCRLF.setSrcdir(destFile.getParentFile());
103        fixCRLF.setIncludes(destFile.getName());
104        fixCRLF.execute();
105        return null;
106    }
107
108    protected List<JClass> sort(List<JClass> classes) {
109        return classes;
110    }
111
112    protected void generateTearDown(PrintWriter out) {
113    }
114
115    protected void generateSetup(PrintWriter out) {
116    }
117
118    /**
119     * Returns all the valid properties available on the current class
120     */
121    public List<JProperty> getProperties() {
122        List<JProperty> answer = new ArrayList<JProperty>();
123        JProperty[] properties = jclass.getDeclaredProperties();
124        for (int i = 0; i < properties.length; i++) {
125            JProperty property = properties[i];
126            if (isValidProperty(property)) {
127                answer.add(property);
128            }
129        }
130        return answer;
131    }
132
133    protected boolean isValidClass(JClass jclass) {
134        if (jclass == null || jclass.getAnnotation("openwire:marshaller") == null) {
135            return false;
136        }
137        return true;
138        // return !manuallyMaintainedClasses.contains(jclass.getSimpleName());
139    }
140
141    protected abstract void generateFile(PrintWriter out) throws Exception;
142
143    protected String getBaseClassName(JClass jclass) {
144        String answer = "BaseDataStructure";
145        if (superclass != null) {
146            String name = superclass.getSimpleName();
147            if (name != null && !name.equals("Object")) {
148                answer = name;
149            }
150        }
151        return answer;
152    }
153
154    protected String getClassName(JClass jclass) {
155        return jclass.getSimpleName();
156    }
157
158    public boolean isAbstractClass() {
159        return jclass != null && jclass.isAbstract();
160    }
161
162    public String getAbstractClassText() {
163        return isAbstractClass() ? "abstract " : "";
164    }
165
166    public boolean isMarshallerAware() {
167        return isMarshallAware(jclass);
168    }
169
170    protected void initialiseManuallyMaintainedClasses() {
171        String[] names = {
172            "ActiveMQDestination", "ActiveMQTempDestination", "ActiveMQQueue", "ActiveMQTopic", "ActiveMQTempQueue", "ActiveMQTempTopic", "BaseCommand", "ActiveMQMessage", "ActiveMQTextMessage",
173            "ActiveMQMapMessage", "ActiveMQBytesMessage", "ActiveMQStreamMessage", "ActiveMQStreamMessage", "DataStructureSupport", "WireFormatInfo", "ActiveMQObjectMessage"
174        };
175
176        for (int i = 0; i < names.length; i++) {
177            manuallyMaintainedClasses.add(names[i]);
178        }
179    }
180
181    public String getBaseClass() {
182        return baseClass;
183    }
184
185    public void setBaseClass(String baseClass) {
186        this.baseClass = baseClass;
187    }
188
189    public String getClassName() {
190        return className;
191    }
192
193    public void setClassName(String className) {
194        this.className = className;
195    }
196
197    public File getDestFile() {
198        return destFile;
199    }
200
201    public void setDestFile(File destFile) {
202        this.destFile = destFile;
203    }
204
205    public JClass getJclass() {
206        return jclass;
207    }
208
209    public void setJclass(JClass jclass) {
210        this.jclass = jclass;
211    }
212
213    public Set<String> getManuallyMaintainedClasses() {
214        return manuallyMaintainedClasses;
215    }
216
217    public void setManuallyMaintainedClasses(Set<String> manuallyMaintainedClasses) {
218        this.manuallyMaintainedClasses = manuallyMaintainedClasses;
219    }
220
221    public String getSimpleName() {
222        return simpleName;
223    }
224
225    public void setSimpleName(String simpleName) {
226        this.simpleName = simpleName;
227    }
228
229    public JClass getSuperclass() {
230        return superclass;
231    }
232
233    public void setSuperclass(JClass superclass) {
234        this.superclass = superclass;
235    }
236
237}