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.PrintWriter;
020import java.util.ArrayList;
021import java.util.Collections;
022import java.util.Comparator;
023import java.util.Iterator;
024import java.util.List;
025
026import org.codehaus.jam.JAnnotation;
027import org.codehaus.jam.JAnnotationValue;
028import org.codehaus.jam.JClass;
029import org.codehaus.jam.JProperty;
030
031/**
032 * 
033 */
034public class CppMarshallingClassesGenerator extends CppMarshallingHeadersGenerator {
035
036    protected String getFilePostFix() {
037        return ".cpp";
038    }
039
040    protected void generateUnmarshalBodyForProperty(PrintWriter out, JProperty property, JAnnotationValue size) {
041        out.print("    ");
042        String setter = property.getSetter().getSimpleName();
043        String type = property.getType().getSimpleName();
044
045        if (type.equals("boolean")) {
046            out.println("info." + setter + "( bs.readBoolean() );");
047        } else if (type.equals("byte")) {
048            out.println("info." + setter + "( DataStreamMarshaller.readByte(dataIn) );");
049        } else if (type.equals("char")) {
050            out.println("info." + setter + "( DataStreamMarshaller.readChar(dataIn) );");
051        } else if (type.equals("short")) {
052            out.println("info." + setter + "( DataStreamMarshaller.readShort(dataIn) );");
053        } else if (type.equals("int")) {
054            out.println("info." + setter + "( DataStreamMarshaller.readInt(dataIn) );");
055        } else if (type.equals("long")) {
056            out.println("info." + setter + "( UnmarshalLong(wireFormat, dataIn, bs) );");
057        } else if (type.equals("String")) {
058            out.println("info." + setter + "( readString(dataIn, bs) );");
059        } else if (type.equals("byte[]") || type.equals("ByteSequence")) {
060            if (size != null) {
061                out.println("info." + setter + "( readBytes(dataIn, " + size.asInt() + ") );");
062            } else {
063                out.println("info." + setter + "( readBytes(dataIn, bs.readBoolean()) );");
064            }
065        } else if (isThrowable(property.getType())) {
066            out.println("info." + setter + "( unmarshalBrokerError(wireFormat, dataIn, bs) );");
067        } else if (isCachedProperty(property)) {
068            out.println("info." + setter + "( (" + type + ") unmarshalCachedObject(wireFormat, dataIn, bs) );");
069        } else {
070            out.println("info." + setter + "( (" + type + ") unmarshalNestedObject(wireFormat, dataIn, bs) );");
071        }
072    }
073
074    protected void generateUnmarshalBodyForArrayProperty(PrintWriter out, JProperty property, JAnnotationValue size) {
075        JClass propertyType = property.getType();
076        String arrayType = propertyType.getArrayComponentType().getSimpleName();
077        String setter = property.getGetter().getSimpleName();
078        out.println();
079        if (size != null) {
080            out.println("    {");
081            out.println("        " + arrayType + "[] value = new " + arrayType + "[" + size.asInt() + "];");
082            out.println("        " + "for( int i=0; i < " + size.asInt() + "; i++ ) {");
083            out.println("            value[i] = (" + arrayType + ") unmarshalNestedObject(wireFormat,dataIn, bs);");
084            out.println("        }");
085            out.println("        info." + setter + "( value );");
086            out.println("    }");
087        } else {
088            out.println("    if (bs.readBoolean()) {");
089            out.println("        short size = DataStreamMarshaller.readShort(dataIn);");
090            out.println("        " + arrayType + "[] value = new " + arrayType + "[size];");
091            out.println("        for( int i=0; i < size; i++ ) {");
092            out.println("            value[i] = (" + arrayType + ") unmarshalNestedObject(wireFormat,dataIn, bs);");
093            out.println("        }");
094            out.println("        info." + setter + "( value );");
095            out.println("    }");
096            out.println("    else {");
097            out.println("        info." + setter + "( null );");
098            out.println("    }");
099        }
100    }
101
102    protected int generateMarshal1Body(PrintWriter out) {
103        List properties = getProperties();
104        int baseSize = 0;
105        for (Iterator iter = properties.iterator(); iter.hasNext();) {
106            JProperty property = (JProperty)iter.next();
107            JAnnotation annotation = property.getAnnotation("openwire:property");
108            JAnnotationValue size = annotation.getValue("size");
109            JClass propertyType = property.getType();
110            String type = propertyType.getSimpleName();
111            String getter = "info." + property.getGetter().getSimpleName() + "()";
112
113            out.print(indent);
114            if (type.equals("boolean")) {
115                out.println("bs.writeBoolean(" + getter + ");");
116            } else if (type.equals("byte")) {
117                baseSize += 1;
118            } else if (type.equals("char")) {
119                baseSize += 1;
120            } else if (type.equals("short")) {
121                baseSize += 1;
122            } else if (type.equals("int")) {
123                baseSize += 1;
124            } else if (type.equals("long")) {
125                out.println("rc += marshal1Long(wireFormat, " + getter + ", bs);");
126            } else if (type.equals("String")) {
127                out.println("rc += writeString(" + getter + ", bs);");
128            } else if (type.equals("byte[]") || type.equals("ByteSequence")) {
129                if (size == null) {
130                    out.println("bs.writeBoolean(" + getter + "!=null);");
131                    out.println("    rc += " + getter + "==null ? 0 : " + getter + ".Length+4;");
132                } else {
133                    baseSize += size.asInt();
134                }
135            } else if (propertyType.isArrayType()) {
136                if (size != null) {
137                    out.println("rc += marshalObjectArrayConstSize(wireFormat, " + getter + ", bs, " + size.asInt() + ");");
138                } else {
139                    out.println("rc += marshalObjectArray(wireFormat, " + getter + ", bs);");
140                }
141            } else if (isThrowable(propertyType)) {
142                out.println("rc += marshalBrokerError(wireFormat, " + getter + ", bs);");
143            } else {
144                if (isCachedProperty(property)) {
145                    out.println("rc += marshal1CachedObject(wireFormat, " + getter + ", bs);");
146                } else {
147                    out.println("rc += marshal1NestedObject(wireFormat, " + getter + ", bs);");
148                }
149            }
150        }
151        return baseSize;
152    }
153
154    protected void generateMarshal2Body(PrintWriter out) {
155        List properties = getProperties();
156        for (Iterator iter = properties.iterator(); iter.hasNext();) {
157            JProperty property = (JProperty)iter.next();
158            JAnnotation annotation = property.getAnnotation("openwire:property");
159            JAnnotationValue size = annotation.getValue("size");
160            JClass propertyType = property.getType();
161            String type = propertyType.getSimpleName();
162            String getter = "info." + property.getGetter().getSimpleName() + "()";
163
164            out.print(indent);
165            if (type.equals("boolean")) {
166                out.println("bs.readBoolean();");
167            } else if (type.equals("byte")) {
168                out.println("DataStreamMarshaller.writeByte(" + getter + ", dataOut);");
169            } else if (type.equals("char")) {
170                out.println("DataStreamMarshaller.writeChar(" + getter + ", dataOut);");
171            } else if (type.equals("short")) {
172                out.println("DataStreamMarshaller.writeShort(" + getter + ", dataOut);");
173            } else if (type.equals("int")) {
174                out.println("DataStreamMarshaller.writeInt(" + getter + ", dataOut);");
175            } else if (type.equals("long")) {
176                out.println("marshal2Long(wireFormat, " + getter + ", dataOut, bs);");
177            } else if (type.equals("String")) {
178                out.println("writeString(" + getter + ", dataOut, bs);");
179            } else if (type.equals("byte[]") || type.equals("ByteSequence")) {
180                if (size != null) {
181                    out.println("dataOut.write(" + getter + ", 0, " + size.asInt() + ");");
182                } else {
183                    out.println("if(bs.readBoolean()) {");
184                    out.println("       DataStreamMarshaller.writeInt(" + getter + ".Length, dataOut);");
185                    out.println("       dataOut.write(" + getter + ");");
186                    out.println("    }");
187                }
188            } else if (propertyType.isArrayType()) {
189                if (size != null) {
190                    out.println("marshalObjectArrayConstSize(wireFormat, " + getter + ", dataOut, bs, " + size.asInt() + ");");
191                } else {
192                    out.println("marshalObjectArray(wireFormat, " + getter + ", dataOut, bs);");
193                }
194            } else if (isThrowable(propertyType)) {
195                out.println("marshalBrokerError(wireFormat, " + getter + ", dataOut, bs);");
196            } else {
197                if (isCachedProperty(property)) {
198                    out.println("marshal2CachedObject(wireFormat, " + getter + ", dataOut, bs);");
199                } else {
200                    out.println("marshal2NestedObject(wireFormat, " + getter + ", dataOut, bs);");
201                }
202            }
203        }
204    }
205
206    protected void generateFile(PrintWriter out) throws Exception {
207        generateLicence(out);
208
209        out.println("#include \"marshal/" + className + ".hpp\"");
210        out.println("");
211        out.println("using namespace apache::activemq::client::marshal;");
212        out.println("");
213        out.println("/*");
214        out.println(" *  Marshalling code for Open Wire Format for " + jclass.getSimpleName() + "");
215        out.println(" *");
216        out.println(" * NOTE!: This file is autogenerated - do not modify!");
217        out.println(" *        if you need to make a change, please see the Groovy scripts in the");
218        out.println(" *        activemq-core module");
219        out.println(" */");
220        out.println("");
221        out.println("" + className + "::" + className + "()");
222        out.println("{");
223        out.println("    // no-op");
224        out.println("}");
225        out.println("");
226        out.println("" + className + "::~" + className + "()");
227        out.println("{");
228        out.println("    // no-op");
229        out.println("}");
230        out.println("");
231
232        if (!isAbstractClass()) {
233            out.println("");
234            out.println("");
235            out.println("IDataStructure* " + className + "::createObject() ");
236            out.println("{");
237            out.println("    return new " + jclass.getSimpleName() + "();");
238            out.println("}");
239            out.println("");
240            out.println("char " + className + "::getDataStructureType() ");
241            out.println("{");
242            out.println("    return " + jclass.getSimpleName() + ".ID_" + jclass.getSimpleName() + ";");
243            out.println("}");
244        }
245
246        out.println("");
247        out.println("    /* ");
248        out.println("     * Un-marshal an object instance from the data input stream");
249        out.println("     */ ");
250        out.println("void " + className + "::unmarshal(ProtocolFormat& wireFormat, Object o, BinaryReader& dataIn, BooleanStream& bs) ");
251        out.println("{");
252        out.println("    base.unmarshal(wireFormat, o, dataIn, bs);");
253
254        List properties = getProperties();
255        boolean marshallerAware = isMarshallerAware();
256        if (!properties.isEmpty() || marshallerAware) {
257            out.println("");
258            out.println("    " + jclass.getSimpleName() + "& info = (" + jclass.getSimpleName() + "&) o;");
259        }
260
261        if (marshallerAware) {
262            out.println("");
263            out.println("    info.beforeUnmarshall(wireFormat);");
264            out.println("        ");
265        }
266
267        generateTightUnmarshalBody(out);
268
269        if (marshallerAware) {
270            out.println("");
271            out.println("    info.afterUnmarshall(wireFormat);");
272        }
273
274        out.println("");
275        out.println("}");
276        out.println("");
277        out.println("");
278        out.println("/*");
279        out.println(" * Write the booleans that this object uses to a BooleanStream");
280        out.println(" */");
281        out.println("int " + className + "::marshal1(ProtocolFormat& wireFormat, Object& o, BooleanStream& bs) {");
282        out.println("    " + jclass.getSimpleName() + "& info = (" + jclass.getSimpleName() + "&) o;");
283
284        if (marshallerAware) {
285            out.println("");
286            out.println("    info.beforeMarshall(wireFormat);");
287        }
288
289        out.println("");
290        out.println("    int rc = base.marshal1(wireFormat, info, bs);");
291
292        int baseSize = generateMarshal1Body(out);
293
294        out.println("");
295        out.println("    return rc + " + baseSize + ";");
296        out.println("}");
297        out.println("");
298        out.println("/* ");
299        out.println(" * Write a object instance to data output stream");
300        out.println(" */");
301        out.println("void " + className + "::marshal2(ProtocolFormat& wireFormat, Object& o, BinaryWriter& dataOut, BooleanStream& bs) {");
302        out.println("    base.marshal2(wireFormat, o, dataOut, bs);");
303
304        if (!properties.isEmpty() || marshallerAware) {
305            out.println("");
306            out.println("    " + jclass.getSimpleName() + "& info = (" + jclass.getSimpleName() + "&) o;");
307        }
308
309        generateMarshal2Body(out);
310
311        if (marshallerAware) {
312            out.println("");
313            out.println("    info.afterMarshall(wireFormat);");
314        }
315
316        out.println("");
317        out.println("}");
318    }
319
320    @SuppressWarnings("unchecked")
321    public void generateFactory(PrintWriter out) {
322        generateLicence(out);
323        out.println("");
324        out.println("// Marshalling code for Open Wire Format");
325        out.println("//");
326        out.println("//");
327        out.println("// NOTE!: This file is autogenerated - do not modify!");
328        out.println("//        if you need to make a change, please see the Groovy scripts in the");
329        out.println("//        activemq-openwire module");
330        out.println("//");
331        out.println("");
332        out.println("#include \"marshal/" + className + ".hpp\"");
333        out.println("");
334
335        List list = new ArrayList(getConcreteClasses());
336        Collections.sort(list, new Comparator() {
337            public int compare(Object o1, Object o2) {
338                JClass c1 = (JClass)o1;
339                JClass c2 = (JClass)o2;
340                return c1.getSimpleName().compareTo(c2.getSimpleName());
341            }
342        });
343
344        for (Iterator iter = list.iterator(); iter.hasNext();) {
345            JClass jclass = (JClass)iter.next();
346            out.println("#include \"marshal/" + jclass.getSimpleName() + "Marshaller.hpp\"");
347        }
348
349        out.println("");
350        out.println("");
351        out.println("using namespace apache::activemq::client::marshal;");
352        out.println("");
353        out.println("");
354        out.println("void MarshallerFactory::configure(ProtocolFormat& format) ");
355        out.println("{");
356
357        for (Iterator iter = list.iterator(); iter.hasNext();) {
358            JClass jclass = (JClass)iter.next();
359            out.println("    format.addMarshaller(new " + jclass.getSimpleName() + "Marshaller());");
360        }
361
362        out.println("");
363        out.println("}");
364
365    }
366}