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     */
017    package org.apache.activemq.openwire.tool;
018    
019    import java.io.File;
020    import java.io.FileWriter;
021    import java.io.PrintWriter;
022    import java.util.ArrayList;
023    import java.util.HashSet;
024    import java.util.Iterator;
025    import java.util.List;
026    import java.util.Set;
027    
028    import org.apache.tools.ant.Project;
029    import org.apache.tools.ant.taskdefs.FixCRLF;
030    import org.codehaus.jam.JClass;
031    import org.codehaus.jam.JProperty;
032    import org.codehaus.jam.JamClassIterator;
033    
034    /**
035     * 
036     */
037    public 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    }