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.PrintWriter;
021import java.util.ArrayList;
022import java.util.Collections;
023import java.util.Comparator;
024import java.util.HashMap;
025import java.util.Iterator;
026import java.util.LinkedHashMap;
027import java.util.List;
028
029import org.codehaus.jam.JAnnotation;
030import org.codehaus.jam.JAnnotationValue;
031import org.codehaus.jam.JClass;
032import org.codehaus.jam.JProperty;
033
034/**
035 * 
036 */
037public class CHeadersGenerator extends SingleSourceGenerator {
038
039    protected String targetDir = "./src/lib/openwire";
040
041    public Object run() {
042        filePostFix = ".h";
043        if (destFile == null) {
044            destFile = new File(targetDir + "/ow_commands_v" + getOpenwireVersion() + ".h");
045        }
046        return super.run();
047    }
048
049    public String getTargetDir() {
050        return targetDir;
051    }
052
053    public void setTargetDir(String targetDir) {
054        this.targetDir = targetDir;
055    }
056
057    protected void generateLicence(PrintWriter out) {
058        out.println("/**");
059        out.println(" * Licensed to the Apache Software Foundation (ASF) under one or more");
060        out.println(" * contributor license agreements.  See the NOTICE file distributed with");
061        out.println(" * this work for additional information regarding copyright ownership.");
062        out.println(" * The ASF licenses this file to You under the Apache License, Version 2.0");
063        out.println(" * (the \"License\"); you may not use this file except in compliance with");
064        out.println(" * the License.  You may obtain a copy of the License at");
065        out.println(" *");
066        out.println(" *      http://www.apache.org/licenses/LICENSE-2.0");
067        out.println(" *");
068        out.println(" * Unless required by applicable law or agreed to in writing, software");
069        out.println(" * distributed under the License is distributed on an \"AS IS\" BASIS,");
070        out.println(" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.");
071        out.println(" * See the License for the specific language governing permissions and");
072        out.println(" * limitations under the License.");
073        out.println(" */");
074    }
075
076    String changeCase(String value) {
077        StringBuffer b = new StringBuffer();
078        char[] cs = value.toCharArray();
079        for (int i = 0; i < cs.length; i++) {
080            char c = cs[i];
081            if (Character.isUpperCase((char)c)) {
082                b.append('_');
083                b.append(Character.toLowerCase((char)c));
084            } else {
085                b.append(c);
086            }
087        }
088        return b.toString();
089    }
090
091    String toPropertyCase(String value) {
092        return value.substring(0, 1).toLowerCase() + value.substring(1);
093    }
094
095    /**
096     * Sort the class list so that base classes come up first.
097     */
098    protected List<JClass> sort(List<JClass> source) {
099        LinkedHashMap<JClass, JClass> rc = new LinkedHashMap<JClass, JClass>();
100        ArrayList<JClass> classes = new ArrayList<JClass>(source);
101        Collections.sort(classes, new Comparator<JClass>() {
102            public int compare(JClass c1, JClass c2) {
103                return c1.getSimpleName().compareTo(c2.getSimpleName());
104            }
105        });
106
107        // lets make a map of all the class names
108        HashMap<JClass, JClass> classNames = new HashMap<JClass, JClass>();
109        for (Iterator iter = classes.iterator(); iter.hasNext();) {
110            JClass c = (JClass)iter.next();
111            classNames.put(c, c);
112        }
113
114        // Add all classes that have no parent first
115        for (Iterator iter = classes.iterator(); iter.hasNext();) {
116            JClass c = (JClass)iter.next();
117            if (!classNames.containsKey(c.getSuperclass())) {
118                rc.put(c, c);
119            }
120        }
121
122        // now lets add the rest
123        for (Iterator iter = classes.iterator(); iter.hasNext();) {
124            JClass c = (JClass)iter.next();
125            if (!rc.containsKey(c)) {
126                rc.put(c, c);
127            }
128        }
129
130        return new ArrayList<JClass>(rc.keySet());
131    }
132
133    void generateFields(PrintWriter out, JClass jclass) {
134
135        if (jclass.getSuperclass() == null || jclass.getSuperclass().getSimpleName().equals("Object")) {
136            out.println("");
137            out.println("   ow_byte structType;");
138        } else {
139            generateFields(out, jclass.getSuperclass());
140        }
141
142        ArrayList<JProperty> properties = new ArrayList<JProperty>();
143        jclass.getDeclaredProperties();
144        for (int i = 0; i < jclass.getDeclaredProperties().length; i++) {
145            JProperty p = jclass.getDeclaredProperties()[i];
146            if (isValidProperty(p)) {
147                properties.add(p);
148            }
149        }
150        for (Iterator<JProperty> iter = properties.iterator(); iter.hasNext();) {
151            JProperty property = iter.next();
152            JAnnotation annotation = property.getGetter().getAnnotation("openwire:property");
153//            JAnnotationValue size = annotation.getValue("size");
154            String name = toPropertyCase(property.getSimpleName());
155//            boolean cached = isCachedProperty(property);
156
157            String type = property.getType().getQualifiedName();
158            if (type.equals("boolean")) {
159                out.println("   ow_" + type + " " + name + ";");
160            } else if (type.equals("byte")) {
161                out.println("   ow_" + type + " " + name + ";");
162            } else if (type.equals("char")) {
163                out.println("   ow_" + type + " " + name + ";");
164            } else if (type.equals("short")) {
165                out.println("   ow_" + type + " " + name + ";");
166            } else if (type.equals("int")) {
167                out.println("   ow_" + type + " " + name + ";");
168            } else if (type.equals("long")) {
169                out.println("   ow_" + type + " " + name + ";");
170            } else if (type.equals("byte[]")) {
171                out.println("   ow_byte_array *" + name + ";");
172            } else if (type.equals("org.apache.activeio.packet.ByteSequence")) {
173                out.println("   ow_byte_array *" + name + ";");
174            } else if (type.equals("org.apache.activeio.packet.ByteSequence")) {
175                out.println("   ow_byte_array *" + name + ";");
176            } else if (type.equals("java.lang.String")) {
177                out.println("   ow_string *" + name + ";");
178            } else {
179                if (property.getType().isArrayType()) {
180                    out.println("   ow_DataStructure_array *" + name + ";");
181                } else if (isThrowable(property.getType())) {
182                    out.println("   ow_throwable *" + name + ";");
183                } else {
184                    out.println("   struct ow_" + property.getType().getSimpleName() + " *" + name + ";");
185                }
186            }
187        }
188    }
189
190    protected void generateSetup(PrintWriter out) {
191        generateLicence(out);
192        out.println("");
193        out.println("/*****************************************************************************************");
194        out.println(" *  ");
195        out.println(" * NOTE!: This file is auto generated - do not modify!");
196        out.println(" *        if you need to make a change, please see the modify the groovy scripts in the");
197        out.println(" *        under src/gram/script and then use maven openwire:generate to regenerate ");
198        out.println(" *        this file.");
199        out.println(" *  ");
200        out.println(" *****************************************************************************************/");
201        out.println(" ");
202        out.println("#ifndef OW_COMMANDS_V" + openwireVersion + "_H");
203        out.println("#define OW_COMMANDS_V" + openwireVersion + "_H");
204        out.println("");
205        out.println("#include \"ow.h\"");
206        out.println("");
207        out.println("#ifdef __cplusplus");
208        out.println("extern \"C\" {");
209        out.println("#endif /* __cplusplus */");
210        out.println("      ");
211        out.println("#define OW_WIREFORMAT_VERSION " + openwireVersion + "");
212
213        out.println("#define OW_WIREFORMAT_STACK_TRACE_MASK     0x00000001;");
214        out.println("#define OW_WIREFORMAT_TCP_NO_DELAY_MASK    0x00000002;");
215        out.println("#define OW_WIREFORMAT_CACHE_MASK           0x00000004;");
216        out.println("#define OW_WIREFORMAT_COMPRESSION_MASK     0x00000008;");
217
218        for (Iterator iterator = sortedClasses.iterator(); iterator.hasNext();) {
219            JClass jclass = (JClass)iterator.next();
220            String name = jclass.getSimpleName();
221            String type = ("ow_" + name).toUpperCase() + "_TYPE";
222            if (!isAbstract(jclass)) {
223                out.println("#define " + type + " " + getOpenWireOpCode(jclass));
224            }
225        }
226
227        out.println("      ");
228        out.println("apr_status_t ow_bitmarshall(ow_bit_buffer *buffer, ow_DataStructure *object);");
229        out.println("apr_status_t ow_marshall(ow_byte_buffer *buffer, ow_DataStructure *object);");
230    }
231
232    protected void generateFile(PrintWriter out) throws Exception {
233
234        String structName = jclass.getSimpleName();
235
236        out.println("");
237        out.println("typedef struct ow_" + structName + " {");
238
239        // This recusivly generates the field definitions of the class and it's
240        // supper classes.
241        generateFields(out, jclass);
242
243        out.println("");
244        out.println("} ow_" + structName + ";");
245        out.println("ow_" + structName + " *ow_" + structName + "_create(apr_pool_t *pool);");
246        out.println("ow_boolean ow_is_a_" + structName + "(ow_DataStructure *object);");
247
248    }
249
250    protected void generateTearDown(PrintWriter out) {
251        out.println("");
252        out.println("#ifdef __cplusplus");
253        out.println("}");
254        out.println("#endif");
255        out.println("");
256        out.println("#endif  /* ! OW_COMMANDS_V" + openwireVersion + "_H */");
257    }
258}