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.PrintWriter;
020    import java.util.ArrayList;
021    import java.util.Collections;
022    import java.util.Comparator;
023    import java.util.Iterator;
024    import java.util.List;
025    
026    import org.codehaus.jam.JAnnotation;
027    import org.codehaus.jam.JAnnotationValue;
028    import org.codehaus.jam.JClass;
029    import org.codehaus.jam.JProperty;
030    
031    /**
032     * 
033     */
034    public 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    }