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.PrintWriter;
021    import java.util.Iterator;
022    import java.util.List;
023    
024    import org.codehaus.jam.JClass;
025    import org.codehaus.jam.JProperty;
026    
027    /**
028     * 
029     */
030    public class CppClassesGenerator extends MultiSourceGenerator {
031    
032        protected String targetDir = "./src/main/cpp";
033    
034        public Object run() {
035            filePostFix = getFilePostFix();
036            if (destDir == null) {
037                destDir = new File(targetDir + "/activemq/command");
038            }
039            return super.run();
040        }
041    
042        protected String getFilePostFix() {
043            return ".cpp";
044        }
045    
046        /**
047         * Converts the Java type to a C++ type name
048         */
049        public String toCppType(JClass type) {
050            String name = type.getSimpleName();
051            if (name.equals("String")) {
052                return "p<string>";
053            } else if (type.isArrayType()) {
054                if (name.equals("byte[]")) {
055                    name = "char[]";
056                } else if (name.equals("DataStructure[]")) {
057                    name = "IDataStructure[]";
058                }
059                return "array<" + name.substring(0, name.length() - 2) + ">";
060            } else if (name.equals("Throwable") || name.equals("Exception")) {
061                return "p<BrokerError>";
062            } else if (name.equals("ByteSequence")) {
063                return "array<char>";
064            } else if (name.equals("boolean")) {
065                return "bool";
066            } else if (name.equals("long")) {
067                return "long long";
068            } else if (name.equals("byte")) {
069                return "char";
070            } else if (name.equals("Command") || name.equals("DataStructure")) {
071                return "p<I" + name + ">";
072            } else if (!type.isPrimitiveType()) {
073                return "p<" + name + ">";
074            } else {
075                return name;
076            }
077        }
078    
079        /**
080         * Converts the Java type to a C++ default value
081         */
082        public String toCppDefaultValue(JClass type) {
083            String name = type.getSimpleName();
084    
085            if (name.equals("boolean")) {
086                return "false";
087            } else if (!type.isPrimitiveType()) {
088                return "NULL";
089            } else {
090                return "0";
091            }
092        }
093    
094        /**
095         * Converts the Java type to the name of the C++ marshal method to be used
096         */
097        public String toMarshalMethodName(JClass type) {
098            String name = type.getSimpleName();
099            if (name.equals("String")) {
100                return "marshalString";
101            } else if (type.isArrayType()) {
102                if (type.getArrayComponentType().isPrimitiveType() && name.equals("byte[]")) {
103                    return "marshalByteArray";
104                } else {
105                    return "marshalObjectArray";
106                }
107            } else if (name.equals("ByteSequence")) {
108                return "marshalByteArray";
109            } else if (name.equals("short")) {
110                return "marshalShort";
111            } else if (name.equals("int")) {
112                return "marshalInt";
113            } else if (name.equals("long")) {
114                return "marshalLong";
115            } else if (name.equals("byte")) {
116                return "marshalByte";
117            } else if (name.equals("double")) {
118                return "marshalDouble";
119            } else if (name.equals("float")) {
120                return "marshalFloat";
121            } else if (name.equals("boolean")) {
122                return "marshalBoolean";
123            } else if (!type.isPrimitiveType()) {
124                return "marshalObject";
125            } else {
126                return name;
127            }
128        }
129    
130        /**
131         * Converts the Java type to the name of the C++ unmarshal method to be used
132         */
133        public String toUnmarshalMethodName(JClass type) {
134            String name = type.getSimpleName();
135            if (name.equals("String")) {
136                return "unmarshalString";
137            } else if (type.isArrayType()) {
138                if (type.getArrayComponentType().isPrimitiveType() && name.equals("byte[]")) {
139                    return "unmarshalByteArray";
140                } else {
141                    return "unmarshalObjectArray";
142                }
143            } else if (name.equals("ByteSequence")) {
144                return "unmarshalByteArray";
145            } else if (name.equals("short")) {
146                return "unmarshalShort";
147            } else if (name.equals("int")) {
148                return "unmarshalInt";
149            } else if (name.equals("long")) {
150                return "unmarshalLong";
151            } else if (name.equals("byte")) {
152                return "unmarshalByte";
153            } else if (name.equals("double")) {
154                return "unmarshalDouble";
155            } else if (name.equals("float")) {
156                return "unmarshalFloat";
157            } else if (name.equals("boolean")) {
158                return "unmarshalBoolean";
159            } else if (!type.isPrimitiveType()) {
160                return "unmarshalObject";
161            } else {
162                return name;
163            }
164        }
165    
166        /**
167         * Converts the Java type to a C++ pointer cast
168         */
169        public String toUnmarshalCast(JClass type) {
170            String name = toCppType(type);
171    
172            if (name.startsWith("p<")) {
173                return "p_cast<" + name.substring(2);
174            } else if (name.startsWith("array<") && (type.isArrayType() && !type.getArrayComponentType().isPrimitiveType()) && !type.getSimpleName().equals("ByteSequence")) {
175                return "array_cast<" + name.substring(6);
176            } else {
177                return "";
178            }
179        }
180    
181        protected void generateLicence(PrintWriter out) {
182            out.println("/**");
183            out.println(" * Licensed to the Apache Software Foundation (ASF) under one or more");
184            out.println(" * contributor license agreements.  See the NOTICE file distributed with");
185            out.println(" * this work for additional information regarding copyright ownership.");
186            out.println(" * The ASF licenses this file to You under the Apache License, Version 2.0");
187            out.println(" * (the \"License\"); you may not use this file except in compliance with");
188            out.println(" * the License.  You may obtain a copy of the License at");
189            out.println(" *");
190            out.println(" *      http://www.apache.org/licenses/LICENSE-2.0");
191            out.println(" *");
192            out.println(" * Unless required by applicable law or agreed to in writing, software");
193            out.println(" * distributed under the License is distributed on an \"AS IS\" BASIS,");
194            out.println(" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.");
195            out.println(" * See the License for the specific language governing permissions and");
196            out.println(" * limitations under the License.");
197            out.println(" */");
198        }
199    
200        protected void generateFile(PrintWriter out) throws Exception {
201            generateLicence(out);
202            out.println("#include \"activemq/command/" + className + ".hpp\"");
203            out.println("");
204            out.println("using namespace apache::activemq::command;");
205            out.println("");
206            out.println("/*");
207            out.println(" *");
208            out.println(" *  Command and marshalling code for OpenWire format for " + className + "");
209            out.println(" *");
210            out.println(" *");
211            out.println(" *  NOTE!: This file is autogenerated - do not modify!");
212            out.println(" *         if you need to make a change, please see the Groovy scripts in the");
213            out.println(" *         activemq-core module");
214            out.println(" *");
215            out.println(" */");
216            out.println("" + className + "::" + className + "()");
217            out.println("{");
218    
219            List properties = getProperties();
220            for (Iterator iter = properties.iterator(); iter.hasNext();) {
221                JProperty property = (JProperty)iter.next();
222                String value = toCppDefaultValue(property.getType());
223                String propertyName = property.getSimpleName();
224                String parameterName = decapitalize(propertyName);
225                out.println("    this->" + parameterName + " = " + value + " ;");
226            }
227            out.println("}");
228            out.println("");
229            out.println("" + className + "::~" + className + "()");
230            out.println("{");
231            out.println("}");
232            out.println("");
233            out.println("unsigned char " + className + "::getDataStructureType()");
234            out.println("{");
235            out.println("    return " + className + "::TYPE ; ");
236            out.println("}");
237            for (Iterator iter = properties.iterator(); iter.hasNext();) {
238                JProperty property = (JProperty)iter.next();
239                String type = toCppType(property.getType());
240                String propertyName = property.getSimpleName();
241                String parameterName = decapitalize(propertyName);
242                out.println("");
243                out.println("        ");
244                out.println("" + type + " " + className + "::get" + propertyName + "()");
245                out.println("{");
246                out.println("    return " + parameterName + " ;");
247                out.println("}");
248                out.println("");
249                out.println("void " + className + "::set" + propertyName + "(" + type + " " + parameterName + ")");
250                out.println("{");
251                out.println("    this->" + parameterName + " = " + parameterName + " ;");
252                out.println("}");
253            }
254            out.println("");
255            out.println("int " + className + "::marshal(p<IMarshaller> marshaller, int mode, p<IOutputStream> ostream) throw (IOException)");
256            out.println("{");
257            out.println("    int size = 0 ;");
258            out.println("");
259            out.println("    size += " + baseClass + "::marshal(marshaller, mode, ostream) ; ");
260    
261            for (Iterator iter = properties.iterator(); iter.hasNext();) {
262                JProperty property = (JProperty)iter.next();
263                String marshalMethod = toMarshalMethodName(property.getType());
264                String propertyName = decapitalize(property.getSimpleName());
265                out.println("    size += marshaller->" + marshalMethod + "(" + propertyName + ", mode, ostream) ; ");
266            }
267            out.println("    return size ;");
268            out.println("}");
269            out.println("");
270            out.println("void " + className + "::unmarshal(p<IMarshaller> marshaller, int mode, p<IInputStream> istream) throw (IOException)");
271            out.println("{");
272            out.println("    " + baseClass + "::unmarshal(marshaller, mode, istream) ; ");
273            for (Iterator iter = properties.iterator(); iter.hasNext();) {
274                JProperty property = (JProperty)iter.next();
275                String cast = toUnmarshalCast(property.getType());
276                String unmarshalMethod = toUnmarshalMethodName(property.getType());
277                String propertyName = decapitalize(property.getSimpleName());
278                out.println("    " + propertyName + " = " + cast + "(marshaller->" + unmarshalMethod + "(mode, istream)) ; ");
279            }
280            out.println("}");
281        }
282    
283        public String getTargetDir() {
284            return targetDir;
285        }
286    
287        public void setTargetDir(String targetDir) {
288            this.targetDir = targetDir;
289        }
290    
291    }