diff options
| author | Kim van der Riet <kpvdr@apache.org> | 2006-11-10 21:04:43 +0000 |
|---|---|---|
| committer | Kim van der Riet <kpvdr@apache.org> | 2006-11-10 21:04:43 +0000 |
| commit | 3b4121f6d81dd4bbf9658813931bc6791aebf2cd (patch) | |
| tree | c5b428e232846dd5dfc878b4413be079343c02fa /gentools | |
| parent | 150ef9fa00ab29d7bd65323d3ae62129c8fdd9e1 (diff) | |
| download | qpid-python-3b4121f6d81dd4bbf9658813931bc6791aebf2cd.tar.gz | |
Latest version of gentools. Java AmqpConstants class added which allows in changes in the <constant>
declarations in spec from version to version. C++ AMQP_Constants.h file still incomplete.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@473472 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'gentools')
22 files changed, 1257 insertions, 116 deletions
diff --git a/gentools/README b/gentools/README index 08df62948d..7b4aabcb30 100644 --- a/gentools/README +++ b/gentools/README @@ -9,6 +9,7 @@ currently configured, this generator will not interact with any file or directory outside of this directory. To build (from this directory): +rm org/apache/qpid/gentools/*.class javac org/apache/qpid/gentools/Main.java Make sure you are using Sun's JDK1.5.0; Eclipse and gcj do not work. diff --git a/gentools/org/apache/qpid/gentools/AmqpConstant.java b/gentools/org/apache/qpid/gentools/AmqpConstant.java new file mode 100644 index 0000000000..310d8c7ae2 --- /dev/null +++ b/gentools/org/apache/qpid/gentools/AmqpConstant.java @@ -0,0 +1,190 @@ +package org.apache.qpid.gentools; + +import java.io.PrintStream; +import java.util.Iterator; +import java.util.TreeMap; + +/** + * @author kpvdr + * Class to represent the <constant> declaration within the AMQP specification. + * Currently, only integer values exist within the specification, however looking forward + * to other possible types in the future, string and double types are also supported. + * + * The <constant> declaration in the specification contains only two attributes: + * name and value. + * + * The value of the constant is mapped against the version(s) for which the name is defined. + * This allows for a change in the value rather than the name only from one version to the next. + */ +@SuppressWarnings("serial") +public class AmqpConstant extends TreeMap<String, AmqpVersionSet> + implements Printable, VersionConsistencyCheck, Comparable<AmqpConstant> +{ + /** + * Constant name as defined by the name attribute of the <constant> declaration. + */ + protected String name; + + /** + * Set of versions for which this constant name is defined. + */ + protected AmqpVersionSet versionSet; + + /** + * Constructor + * @param name Constant name as defined by the name attribute of the <constant> declaration. + * @param value Constant value as defined by the value attribute of the <constant> declaration. + * @param version AMQP version for which this constant is defined + */ + public AmqpConstant (String name, String value, AmqpVersion version) + { + this.name = name; + versionSet = new AmqpVersionSet(version); + AmqpVersionSet valueVersionSet = new AmqpVersionSet(version); + put(value, valueVersionSet); + } + + /** + * Constructor + * @param name Constant name as defined by the name attribute of the <constant> declaration. + * @param value Constant value as defined by the value attribute of the <constant> declaration. + * @param version AMQP version for which this constant is defined + */ + public AmqpConstant (String name, int value, AmqpVersion version) + { + this.name = name; + versionSet = new AmqpVersionSet(version); + AmqpVersionSet valueVersionSet = new AmqpVersionSet(version); + put(String.valueOf(value), valueVersionSet); + } + + /** + * Constructor + * @param name Constant name as defined by the name attribute of the <constant> declaration. + * @param value Constant value as defined by the value attribute of the <constant> declaration. + * @param version AMQP version for which this constant is defined + */ + public AmqpConstant (String name, double value, AmqpVersion version) + { + this.name = name; + versionSet = new AmqpVersionSet(version); + AmqpVersionSet valueVersionSet = new AmqpVersionSet(version); + put(String.valueOf(value), valueVersionSet); + } + + /** + * Get the name of this constant. + * @return Name of this constant, being the name attribute of the <constant> declaration + * represented by this class. + */ + public String getName() + { + return name; + } + + /** + * Get the value of this constant as a String. + * @param version AMQP version for which this value is required. + * @return Value of this constant, being the value attribute of the <constant> declaration + * represented by this class. + * @throws AmqpTypeMappingException when a value is requested for a version for which it is not + * defined in the AMQP specifications. + */ + public String getStringValue(AmqpVersion version) + throws AmqpTypeMappingException + { + Iterator<String> sItr = keySet().iterator(); + while (sItr.hasNext()) + { + String value = sItr.next(); + AmqpVersionSet versionSet = get(value); + if (versionSet.contains(version)) + return value; + } + throw new AmqpTypeMappingException("Unable to find value for constant \"" + name + + "\" for version " + version.toString() + "."); + } + + /** + * Get the value of this constant as an integer. + * @param version AMQP version for which this value is required. + * @return Value of this constant, being the value attribute of the <constant> declaration + * represented by this class. + * @throws AmqpTypeMappingException when a value is requested for a version for which it is not + * defined in the AMQP specifications. + */ + public int getIntegerValue(AmqpVersion version) + throws AmqpTypeMappingException + { + return Integer.parseInt(getStringValue(version)); + } + + /** + * Get the value of this constant as a double. + * @param version AMQP version for which this value is required. + * @return Value of this constant, being the value attribute of the <constant> declaration + * represented by this class. + * @throws AmqpTypeMappingException when a value is requested for a version for which it is not + * defined in the AMQP specifications. + */ + public double getDoubleValue(AmqpVersion version) + throws AmqpTypeMappingException + { + return Double.parseDouble(getStringValue(version)); + } + + /** + * Get the version set for this constant. It contains the all the versions for which this + * constant name exists. + * @return Set of versions for which this constant exists. + */ + public AmqpVersionSet getVersionSet() + { + return versionSet; + } + + /* (non-Javadoc) + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + + public int compareTo(AmqpConstant other) + { + int res = name.compareTo(other.name); + if (res != 0) + return res; + return versionSet.compareTo(other.versionSet); + } + + /* (non-Javadoc) + * @see org.apache.qpid.gentools.VersionConsistencyCheck#isVersionConsistent(org.apache.qpid.gentools.AmqpVersionSet) + */ + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + if (size() != 1) + return false; + return get(firstKey()).equals(globalVersionSet); + } + + /* (non-Javadoc) + * @see org.apache.qpid.gentools.Printable#print(java.io.PrintStream, int, int) + */ + public void print(PrintStream out, int marginSize, int tabSize) + { + String margin = Utils.createSpaces(marginSize); + String tab = Utils.createSpaces(tabSize); + if (size() == 1) + { + out.println(margin + tab + "[C] " + name + " = \"" + firstKey() + "\" " + versionSet); + } + else + { + out.println(margin + tab + "[C] " + name + ": " + versionSet); + Iterator<String> sItr = keySet().iterator(); + while (sItr.hasNext()) + { + String value = sItr.next(); + out.println(margin + tab + tab + "= \"" + value + "\" " + get(value)); + } + } + } +} diff --git a/gentools/org/apache/qpid/gentools/AmqpConstantSet.java b/gentools/org/apache/qpid/gentools/AmqpConstantSet.java new file mode 100644 index 0000000000..bca717bdcc --- /dev/null +++ b/gentools/org/apache/qpid/gentools/AmqpConstantSet.java @@ -0,0 +1,115 @@ +package org.apache.qpid.gentools; + +import java.io.PrintStream; +import java.util.Iterator; +import java.util.TreeSet; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * @author kpvdr + * This class implements a set collection for {@link #AmqpConstant AmqpConstant} objects, being the collection + * of constants accumulated from various AMQP specification files processed. Each name occurs once only in the set. + * The {@link #AmqpConstant AmqpConstant} objects (derived from {@link java.util#TreeMap TreeMap}) keep track of + * the value and version(s) assigned to this name. + */ +@SuppressWarnings("serial") +public class AmqpConstantSet extends TreeSet<AmqpConstant> implements Printable, NodeAware, Comparable<AmqpConstantSet> +{ + public LanguageConverter converter; + + public AmqpConstantSet(LanguageConverter converter) + { + this.converter = converter; + this.converter.setConstantSet(this); + } + + /* (non-Javadoc) + * @see org.apache.qpid.gentools.NodeAware#addFromNode(org.w3c.dom.Node, int, org.apache.qpid.gentools.AmqpVersion) + */ + public void addFromNode(Node node, int ordinal, AmqpVersion version) + throws AmqpParseException, AmqpTypeMappingException + { + NodeList nodeList = node.getChildNodes(); + for (int i=0; i<nodeList.getLength(); i++) + { + Node childNode = nodeList.item(i); + if (childNode.getNodeName().compareTo(Utils.ELEMENT_CONSTANT) == 0) + { + String name = converter.prepareDomainName(Utils.getNamedAttribute(childNode, Utils.ATTRIBUTE_NAME)); + String value = Utils.getNamedAttribute(childNode, Utils.ATTRIBUTE_VALUE); + // Find this name in the existing set of objects + boolean foundName = false; + Iterator<AmqpConstant> cItr = iterator(); + while (cItr.hasNext() && !foundName) + { + AmqpConstant thisConstant = cItr.next(); + if (name.compareTo(thisConstant.name) == 0) + { + foundName = true; + thisConstant.versionSet.add(version); + // Now, find the value in the map + boolean foundValue = false; + Iterator<String> vItr = thisConstant.keySet().iterator(); + while (vItr.hasNext() && !foundValue) + { + String thisValue = vItr.next(); + if (value.compareTo(thisValue) == 0) + { + foundValue = true; + // Add this version to existing version set. + AmqpVersionSet versionSet = thisConstant.get(thisValue); + versionSet.add(version); + } + } + // Check that the value was found - if not, add it + if (!foundValue) + { + thisConstant.put(value, new AmqpVersionSet(version)); + } + } + } + // Check that the name was found - if not, add it + if (!foundName) + { + add(new AmqpConstant(name, value, version)); + } + } + } + } + + /* (non-Javadoc) + * @see org.apache.qpid.gentools.Printable#print(java.io.PrintStream, int, int) + */ + public void print(PrintStream out, int marginSize, int tabSize) + { + out.println(Utils.createSpaces(marginSize) + "Constants: "); + Iterator<AmqpConstant> cItr = iterator(); + while (cItr.hasNext()) + { + cItr.next().print(out, marginSize, tabSize); + } + } + + /* (non-Javadoc) + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public int compareTo(AmqpConstantSet other) + { + int res = size() - other.size(); + if (res != 0) + return res; + Iterator<AmqpConstant> cItr = iterator(); + Iterator<AmqpConstant> oItr = other.iterator(); + while (cItr.hasNext() && oItr.hasNext()) + { + AmqpConstant constant = cItr.next(); + AmqpConstant oConstant = oItr.next(); + res = constant.compareTo(oConstant); + if (res != 0) + return res; + } + return 0; + } +} diff --git a/gentools/org/apache/qpid/gentools/AmqpDomainMap.java b/gentools/org/apache/qpid/gentools/AmqpDomainMap.java index 656239a626..ffa188f263 100644 --- a/gentools/org/apache/qpid/gentools/AmqpDomainMap.java +++ b/gentools/org/apache/qpid/gentools/AmqpDomainMap.java @@ -90,8 +90,6 @@ public class AmqpDomainMap extends TreeMap<String, AmqpDomain> implements Printa // return itself as the type. if (domainType == null) { -// return converter.getDomainType(domainName, version); -System.out.println("@DEBUG Unable to find domain " + domainName); return domainName; } try @@ -108,8 +106,8 @@ System.out.println("@DEBUG Unable to find domain " + domainName); public void print(PrintStream out, int marginSize, int tabSize) { + out.println(Utils.createSpaces(marginSize) + "Domain Map:"); Iterator<String> i = keySet().iterator(); - out.println(Utils.createSpaces(marginSize) + "Domain Map:"); while (i.hasNext()) { String domainName = i.next(); diff --git a/gentools/org/apache/qpid/gentools/AmqpVersion.java b/gentools/org/apache/qpid/gentools/AmqpVersion.java index f3f4f5833b..b363003993 100644 --- a/gentools/org/apache/qpid/gentools/AmqpVersion.java +++ b/gentools/org/apache/qpid/gentools/AmqpVersion.java @@ -47,6 +47,11 @@ public class AmqpVersion implements Comparable<AmqpVersion> return 0; } + public String namespace() + { + return "ver_" + major + "_" + minor; + } + public String toString() { return major + "-" + minor; diff --git a/gentools/org/apache/qpid/gentools/AmqpVersionSet.java b/gentools/org/apache/qpid/gentools/AmqpVersionSet.java index 608a319146..c2da24c602 100644 --- a/gentools/org/apache/qpid/gentools/AmqpVersionSet.java +++ b/gentools/org/apache/qpid/gentools/AmqpVersionSet.java @@ -19,13 +19,41 @@ package org.apache.qpid.gentools; import java.io.PrintStream; //import java.util.ArrayList; +import java.util.Iterator; import java.util.TreeSet; @SuppressWarnings("serial") -public class AmqpVersionSet extends TreeSet<AmqpVersion> implements Printable +public class AmqpVersionSet extends TreeSet<AmqpVersion> implements Printable, Comparable<AmqpVersionSet> { + public AmqpVersionSet() + { + } + + public AmqpVersionSet(AmqpVersion version) + { + add(version); + } + public void print(PrintStream out, int marginSize, int tabSize) { out.print(Utils.createSpaces(marginSize) + "Version Set: " + toString()); } + + public int compareTo(AmqpVersionSet other) + { + int res = size() - other.size(); + if (res != 0) + return res; + Iterator<AmqpVersion> vItr = iterator(); + Iterator<AmqpVersion> oItr = other.iterator(); + while (vItr.hasNext() && oItr.hasNext()) + { + AmqpVersion version = vItr.next(); + AmqpVersion oVersion = oItr.next(); + res = version.compareTo(oVersion); + if (res != 0) + return res; + } + return 0; + } } diff --git a/gentools/org/apache/qpid/gentools/CppGenerator.java b/gentools/org/apache/qpid/gentools/CppGenerator.java index b89173ae6d..0910307f29 100644 --- a/gentools/org/apache/qpid/gentools/CppGenerator.java +++ b/gentools/org/apache/qpid/gentools/CppGenerator.java @@ -295,9 +295,9 @@ public class CppGenerator extends Generator if (token.compareTo("${FIELD}") == 0 && field != null) return field.name; if (token.compareTo(versionNamespaceStartToken) == 0 && version != null) - return "namespace ver_" + version.getMajor() + "_" + version.getMinor() + cr + "{"; + return "namespace " + version.namespace() + cr + "{"; if (token.compareTo(versionNamespaceEndToken) == 0 && version != null) - return "} // namespace ver_" + version.getMajor() + "_" + version.getMinor(); + return "} // namespace " + version.namespace(); throw new AmqpTemplateException("Template token " + token + " unknown."); } @@ -317,21 +317,73 @@ public class CppGenerator extends Generator // ClientOperations.h if (token.compareTo("${coh_method_handler_get_method}") == 0) { - codeSnippet = generateMethodHandlerGetMethods(model, false, 4); + codeSnippet = generateOpsMethodHandlerGetMethods(model, false, 4); } else if (token.compareTo("${coh_inner_class}") == 0) { - codeSnippet = generateInnerClasses(model, false, 4, 4); + codeSnippet = generateOpsInnerClasses(model, false, 4, 4); } // ServerOperations.h else if (token.compareTo("${soh_method_handler_get_method}") == 0) { - codeSnippet = generateMethodHandlerGetMethods(model, true, 4); + codeSnippet = generateOpsMethodHandlerGetMethods(model, true, 4); } else if (token.compareTo("${soh_inner_class}") == 0) { - codeSnippet = generateInnerClasses(model, true, 4, 4); + codeSnippet = generateOpsInnerClasses(model, true, 4, 4); + } + + // ClientProxy.h/cpp + else if (token.compareTo("${cph_inner_class_instance}") == 0) + { + codeSnippet = generateProxyInnerClassInstances(model, false, 4); + } + else if (token.compareTo("${cph_inner_class_get_method}") == 0) + { + codeSnippet = generateProxyInnerClassGetMethodDecls(model, false, 4); + } + else if (token.compareTo("${cph_inner_class_defn}") == 0) + { + codeSnippet = generateProxyInnerClassDefinitions(model, false, 4, 4); + } + else if (token.compareTo("${cpc_constructor_initializer}") == 0) + { + codeSnippet = generateProxyConstructorInitializers(model, false, 4); + } + else if (token.compareTo("${cpc_inner_class_get_method}") == 0) + { + codeSnippet = generateProxyInnerClassGetMethodImpls(model, false, 0, 4); + } + else if (token.compareTo("${cpc_inner_class_impl}") == 0) + { + codeSnippet = generateProxyInnerClassImpl(model, false, 0, 4); + } + + // SerrverProxy.h/cpp + else if (token.compareTo("${sph_inner_class_instance}") == 0) + { + codeSnippet = generateProxyInnerClassInstances(model, true, 4); + } + else if (token.compareTo("${sph_inner_class_get_method}") == 0) + { + codeSnippet = generateProxyInnerClassGetMethodDecls(model, true, 4); + } + else if (token.compareTo("${sph_inner_class_defn}") == 0) + { + codeSnippet = generateProxyInnerClassDefinitions(model, true, 4, 4); + } + else if (token.compareTo("${spc_constructor_initializer}") == 0) + { + codeSnippet = generateProxyConstructorInitializers(model, true, 4); + } + else if (token.compareTo("${spc_inner_class_get_method}") == 0) + { + codeSnippet = generateProxyInnerClassGetMethodImpls(model, true, 0, 4); + } + else if (token.compareTo("${spc_inner_class_impl}") == 0) + { + codeSnippet = generateProxyInnerClassImpl(model, true, 0, 4); } else // Oops! @@ -405,12 +457,99 @@ public class CppGenerator extends Generator } sb.insert(listMarkerStartIndex, codeSnippet); } + + @Override + protected void processConstantList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpConstantSet constantSet) + throws AmqpTemplateException, AmqpTypeMappingException + { + String codeSnippet; + int lend = sb.indexOf(cr, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokxStart = tline.indexOf('$'); + String token = tline.substring(tokxStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + if (token.compareTo("${ch_static_const_decl}") == 0) + { + codeSnippet = generateConstantDeclarations(constantSet, 4, 4); + } + else if (token.compareTo("${ch_get_value_method}") == 0) + { + codeSnippet = generateConstantGetMethods(constantSet, 4, 4); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } // === Protected and private helper functions unique to C++ implementation === + + // Methods for generation of code snippets for AMQP_Constants.h file + + protected String generateConstantDeclarations(AmqpConstantSet constantSet, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + Iterator<AmqpConstant> cItr = constantSet.iterator(); + while (cItr.hasNext()) + { + AmqpConstant constant = cItr.next(); + // Do nothing if version is consistent across all versions + if (!constant.isVersionConsistent(globalVersionSet)) + { + + } + } + return sb.toString(); + } + + protected String generateConstantGetMethods(AmqpConstantSet constantSet, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + Iterator<AmqpConstant> cItr = constantSet.iterator(); + while (cItr.hasNext()) + { + AmqpConstant constant = cItr.next(); + if (constant.isVersionConsistent(globalVersionSet)) + { + // return a constant + String value = constant.firstKey(); + sb.append(indent + "public const char* " + constant.name + "() const { return \"" + + constant.firstKey() + "\"; }" + cr); + sb.append(indent + "public const string& " + constant.name + "AsString() const { return new string(\"" + + constant.firstKey() + "\"); }" + cr); + if (Utils.containsOnlyDigits(value)) + { + sb.append(indent + "public int " + constant.name + "AsInt() const { return " + + constant.firstKey() + "; }" + cr); + } + if (Utils.containsOnlyDigitsAndDecimal(value)) + { + sb.append(indent + "public double " + constant.name + "AsDouble() const { return (double)" + + constant.firstKey() + "; }" + cr); + } + sb.append(cr); + } + else + { + // return value from version map + } + } + return sb.toString(); + } - // Methods used for generation of code snippets for ServerOperations class generation + // Methods used for generation of code snippets for Server/ClientOperations class generation - protected String generateMethodHandlerGetMethods(AmqpModel model, boolean serverFlag, int indentSize) + protected String generateOpsMethodHandlerGetMethods(AmqpModel model, boolean serverFlag, int indentSize) { String indent = Utils.createSpaces(indentSize); StringBuffer sb = new StringBuffer(); @@ -437,7 +576,7 @@ public class CppGenerator extends Generator return sb.toString(); } - protected String generateInnerClasses(AmqpModel model, boolean serverFlag, int indentSize, int tabSize) + protected String generateOpsInnerClasses(AmqpModel model, boolean serverFlag, int indentSize, int tabSize) throws AmqpTypeMappingException { String indent = Utils.createSpaces(indentSize); @@ -460,26 +599,28 @@ public class CppGenerator extends Generator sb.append(cr); sb.append(indent + "{" + cr); sb.append(indent + "private:" + cr); - sb.append(indent + tab + "u_int8_t major;" + cr); - sb.append(indent + tab + "u_int8_t minor;" + cr); + sb.append(indent + tab + "ProtocolVersion version;" + cr); sb.append(cr); sb.append(indent + "public:" + cr); sb.append(indent + tab + "// Constructors and destructors" + cr); sb.append(cr); sb.append(indent + tab + className + - "(u_int8_t major, u_int8_t minor) : major(major), minor(minor) {}" + cr); + "(u_int8_t major, u_int8_t minor) : version(major, minor) {}" + cr); + sb.append(indent + tab + className + + "(ProtocolVersion version) : version(version) {}" + cr); sb.append(indent + tab + "virtual ~" + className + "() {}" + cr); sb.append(cr); sb.append(indent + tab + "// Protocol methods" + cr); sb.append(cr); - sb.append(generateInnerClassMethods(thisClass, serverFlag, indentSize + tabSize, tabSize)); + sb.append(generateInnerClassMethods(thisClass, serverFlag, true, indentSize + tabSize, tabSize)); sb.append(indent + "}; // class " + className + cr); first = false; } return sb.toString(); } - protected String generateInnerClassMethods(AmqpClass thisClass, boolean serverFlag, int indentSize, int tabSize) + protected String generateInnerClassMethods(AmqpClass thisClass, boolean serverFlag, + boolean abstractMethodFlag, int indentSize, int tabSize) throws AmqpTypeMappingException { String indent = Utils.createSpaces(indentSize); @@ -504,11 +645,14 @@ public class CppGenerator extends Generator if (!first) sb.append(cr); sb.append(indent + "virtual void " + methodName + "( u_int16_t channel"); - sb.append(generateMethodParameterList(fieldMap, indentSize + (5*tabSize))); + sb.append(generateMethodParameterList(fieldMap, indentSize + (5*tabSize), true, true)); + sb.append(" )"); + if (abstractMethodFlag) + sb.append(" = 0"); + sb.append(";"); if (versionSet.size() != globalVersionSet.size()) - sb.append(" ) = 0; // AMQP Version(s) " + versionSet + cr); - else - sb.append(" ) = 0;" + cr); + sb.append(" // AMQP Version(s) " + versionSet); + sb.append(cr); first = false; } } @@ -516,22 +660,263 @@ public class CppGenerator extends Generator return sb.toString(); } - protected String generateMethodParameterList(AmqpOrdinalFieldMap fieldMap, int indentSize) + // Methods used for generation of code snippets for Server/ClientProxy class generation + + protected String generateProxyInnerClassInstances(AmqpModel model, boolean serverFlag, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + Iterator<String> cItr = model.classMap.keySet().iterator(); + while (cItr.hasNext()) + { + AmqpClass thisClass = model.classMap.get(cItr.next()); + String instanceName = parseForReservedWords(Utils.firstLower(thisClass.name), null); + String className = parseForReservedWords(thisClass.name, null); + sb.append(indent + instanceName + " " + className + ";"); + if (thisClass.versionSet.size() != globalVersionSet.size()) + sb.append(" // AMQP Version(s) " + thisClass.versionSet + cr); + else + sb.append(cr); + } + return sb.toString(); + } + + protected String generateProxyInnerClassGetMethodDecls(AmqpModel model, boolean serverFlag, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + Iterator<String> cItr = model.classMap.keySet().iterator(); + while (cItr.hasNext()) + { + AmqpClass thisClass = model.classMap.get(cItr.next()); + String className = parseForReservedWords(thisClass.name, null); + sb.append(indent + className + "& get" + className + "();"); + if (thisClass.versionSet.size() != globalVersionSet.size()) + sb.append(" // AMQP Version(s) " + thisClass.versionSet + cr); + else + sb.append(cr); + } + return sb.toString(); + } + + protected String generateProxyInnerClassDefinitions(AmqpModel model, boolean serverFlag, + int indentSize, int tabSize) throws AmqpTypeMappingException { String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); StringBuffer sb = new StringBuffer(); boolean first = true; - Iterator<Integer> pItr = fieldMap.keySet().iterator(); - while(pItr.hasNext()) + Iterator<String> cItr = model.classMap.keySet().iterator(); + while (cItr.hasNext()) { - String[] field = fieldMap.get(pItr.next()); - if (first) - sb.append("," + cr); - sb.append(indent + setRef(field[FIELD_DOMAIN]) + " " + field[FIELD_NAME] + - (pItr.hasNext() ? "," + cr : "")); + AmqpClass thisClass = model.classMap.get(cItr.next()); + String className = thisClass.name; + String superclassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Operations::" + + thisClass.name + "Handler"; + if (!first) + sb.append(cr); + sb.append(indent + "// ==================== class " + className + + " ====================" + cr); + sb.append(indent + "class " + className + " : virtual public " + superclassName); + if (thisClass.versionSet.size() != globalVersionSet.size()) + sb.append(" // AMQP Version(s) " + thisClass.versionSet + cr); + else + sb.append(cr); + sb.append(indent + "{" + cr); + sb.append(indent + "private:" + cr); + sb.append(indent + tab + "ProtocolVersion version;" + cr); + sb.append(indent + tab + "OutputHandler* out;" + cr); + sb.append(cr); + sb.append(indent + "public:" + cr); + sb.append(indent + tab + "// Constructors and destructors" + cr); + sb.append(cr); + sb.append(indent + tab + className + "(OutputHandler* out, u_int8_t major, u_int8_t minor) : " + cr); + sb.append(indent + tab + tab + "out(out), version(major, minor) {}" + cr); + sb.append(indent + tab + className + "(OutputHandler* out, ProtocolVersion version) : " + cr); + sb.append(indent + tab + tab + "out(out), version(version) {}" + cr); + sb.append(indent + tab + "virtual ~" + className + "() {}" + cr); + sb.append(cr); + sb.append(indent + tab + "// Protocol methods" + cr); + sb.append(cr); + sb.append(generateInnerClassMethods(thisClass, serverFlag, false, indentSize + tabSize, tabSize)); + sb.append(indent + "}; // class " + className + cr); first = false; } + return sb.toString(); + } + + protected String generateProxyConstructorInitializers(AmqpModel model, boolean serverFlag, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(indent + "out(out)," + cr); + sb.append(indent + "major(major)," + cr); + sb.append(indent + "minor(minor)"); + Iterator<String> cItr = model.classMap.keySet().iterator(); + while (cItr.hasNext()) + { + AmqpClass thisClass = model.classMap.get(cItr.next()); + String instanceName = parseForReservedWords(Utils.firstLower(thisClass.name), null); + sb.append("," + cr); + sb.append(indent + instanceName + "(out)"); + if (!cItr.hasNext()) + sb.append(cr); + } + return sb.toString(); + } + + protected String generateProxyInnerClassGetMethodImpls(AmqpModel model, boolean serverFlag, + int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + Iterator<String> cItr = model.classMap.keySet().iterator(); + while (cItr.hasNext()) + { + AmqpClass thisClass = model.classMap.get(cItr.next()); + String className = thisClass.name; + String instanceName = parseForReservedWords(Utils.firstLower(thisClass.name), null); + sb.append(indent + outerClassName + "::" + className + "& " + + outerClassName + "::get" + className + "()" + cr); + sb.append(indent + "{" + cr); + if (thisClass.versionSet.size() != globalVersionSet.size()) + { + sb.append(indent + tab + "if (!" + generateVersionCheck(thisClass.versionSet) + ")" + cr); + sb.append(indent + tab + tab + "throw new ProtocolVersionException();" + cr); + } + sb.append(indent + tab + "return " + instanceName + ";" + cr); + sb.append(indent + "}" + cr); + if (cItr.hasNext()) + sb.append(cr); + } + return sb.toString(); + } + + protected String generateProxyInnerClassImpl(AmqpModel model, boolean serverFlag, + int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + boolean firstClassFlag = true; + Iterator<String> cItr = model.classMap.keySet().iterator(); + while (cItr.hasNext()) + { + AmqpClass thisClass = model.classMap.get(cItr.next()); + String className = thisClass.name; + if (!firstClassFlag) + sb.append(cr); + sb.append(indent + "// ==================== class " + className + + " ====================" + cr); + sb.append(generateInnerClassMethodImpls(thisClass, serverFlag, indentSize, tabSize)); + firstClassFlag = false; + } + return sb.toString(); + } + + protected String generateInnerClassMethodImpls(AmqpClass thisClass, boolean serverFlag, + int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String outerclassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + boolean first = true; + Iterator<String> mItr = thisClass.methodMap.keySet().iterator(); + while (mItr.hasNext()) + { + AmqpMethod method = thisClass.methodMap.get(mItr.next()); + String methodBodyClassName = thisClass.name + Utils.firstUpper(method.name) + "Body"; + boolean clientChassisFlag = method.clientMethodFlagMap.isSet(); + boolean serverChassisFlag = method.serverMethodFlagMap.isSet(); + if ((serverFlag && serverChassisFlag) || (!serverFlag && clientChassisFlag)) + { + String methodName = parseForReservedWords(method.name, thisClass.name); + AmqpOverloadedParameterMap overloadededParameterMap = + method.getOverloadedParameterLists(thisClass.versionSet, this); + Iterator<AmqpOrdinalFieldMap> ofmItr = overloadededParameterMap.keySet().iterator(); + while (ofmItr.hasNext()) + { + AmqpOrdinalFieldMap fieldMap = ofmItr.next(); + AmqpVersionSet versionSet = overloadededParameterMap.get(fieldMap); + boolean versionConsistentFlag = versionSet.size() == globalVersionSet.size(); + if (!first) + sb.append(cr); + sb.append(indent + "void " + outerclassName + "::" + methodName + "( u_int16_t channel"); + sb.append(generateMethodParameterList(fieldMap, indentSize + (5*tabSize), true, true)); + sb.append(" )"); + if (!versionConsistentFlag) + sb.append(" // AMQP Version(s) " + versionSet); + sb.append(cr); + sb.append(indent + "{" + cr); + sb.append(generateMethodBodyCallContext(fieldMap, outerclassName, methodBodyClassName, + versionSet, indentSize + tabSize, tabSize)); + sb.append(indent + "}" + cr); + sb.append(cr); + first = false; + } + } + } + return sb.toString(); + } + + protected String generateMethodBodyCallContext(AmqpOrdinalFieldMap fieldMap, String outerclassName, + String methodBodyClassName, AmqpVersionSet versionSet, int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + if (versionSet.size() == globalVersionSet.size()) + { + sb.append(generateMethodBodyCall(fieldMap, methodBodyClassName, null, indentSize, tabSize)); + } + else + { + boolean firstOverloadedMethodFlag = true; + Iterator<AmqpVersion> vItr = versionSet.iterator(); + while (vItr.hasNext()) + { + AmqpVersion version = vItr.next(); + sb.append(indent); + if (!firstOverloadedMethodFlag) + sb.append("else "); + sb.append("if (" + generateVersionCheck(version) + ")" + cr); + sb.append(indent + "{" + cr); + sb.append(generateMethodBodyCall(fieldMap, methodBodyClassName, version, + indentSize + tabSize, tabSize)); + sb.append(indent + "}" + cr); + firstOverloadedMethodFlag = false; + } + sb.append(indent + "else" + cr); + sb.append(indent + "{" + cr); + sb.append(indent + tab + "stringstream ss;" + cr); + sb.append(indent + tab + "ss << \"Call to " + outerclassName + "::" + methodBodyClassName + + "(u_int16_t" + generateMethodParameterList(fieldMap, 0, true, false) + ")\"" + cr); + sb.append(indent + tab + tab + "<< \" is invalid for AMQP version \" << version.toString() << \".\";" + cr); + sb.append(indent + tab + "throw new ProtocolVersionException(ss.str());" + cr); + sb.append(indent + "}" + cr); + } + return sb.toString(); + } + + protected String generateMethodBodyCall(AmqpOrdinalFieldMap fieldMap, String methodBodyClassName, + AmqpVersion version, int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + String namespace = version != null ? version.namespace() + "::" : ""; + StringBuffer sb = new StringBuffer(indent + "out->send( new AMQP_Frame( channel," + cr); + sb.append(indent + tab + "new " + namespace + methodBodyClassName + "("); + sb.append(generateMethodParameterList(fieldMap, indentSize + (5*tabSize), false, true)); + sb.append(" )));" + cr); return sb.toString(); } @@ -857,18 +1242,78 @@ public class CppGenerator extends Generator return sb.toString(); } - private String parseForReservedWords(String methodName, String className) + protected String generateMethodParameterList(AmqpOrdinalFieldMap fieldMap, int indentSize, + boolean leadingCommaFlag, boolean fieldNameFlag) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + boolean first = true; + Iterator<Integer> pItr = fieldMap.keySet().iterator(); + while(pItr.hasNext()) + { + String[] field = fieldMap.get(pItr.next()); + if (first && leadingCommaFlag) + { + sb.append("," + (fieldNameFlag ? cr : " ")); + } + if (!first || leadingCommaFlag) + { + sb.append(indent); + } + sb.append(setRef(field[FIELD_DOMAIN]) + + (fieldNameFlag ? " " + field[FIELD_NAME] : "") + + (pItr.hasNext() ? "," + (fieldNameFlag ? cr : " ") : "")); + first = false; + } + return sb.toString(); + } + + private String generateVersionCheck(AmqpVersion version) + { + return "version.equals(" + version.getMajor() + ", " + version.getMinor() + ")"; + } + + private String generateVersionCheck(AmqpVersionSet versionSet) + throws AmqpTypeMappingException + { + StringBuffer sb = new StringBuffer(); + AmqpVersion[] versionArray = new AmqpVersion[versionSet.size()]; + versionSet.toArray(versionArray); + for (int i=0; i<versionArray.length; i++) + { + if (i != 0) + sb.append(" || "); + if (versionArray.length > 1) + sb.append("("); + sb.append("version.equals(" + versionArray[i].getMajor() + ", " + versionArray[i].getMinor() + ")"); + if (versionArray.length > 1) + sb.append(")"); + } + return sb.toString(); + } + + private String parseForReservedWords(String name, String className) { for (int i=0; i<cppReservedWords.length; i++) - if (methodName.compareTo(cppReservedWords[i]) == 0) + if (name.compareTo(cppReservedWords[i]) == 0) { - System.out.println("WARNING: Found method \"" + methodName + - "\" in class \"" + className + - "\", which is a C/C++ reserved word. " + - "Changing generated method name to \"" + methodName + "_\"."); - return methodName + "_"; + if (className == null) + { + System.out.println("WARNING: Found name \"" + name + + "\", which is a C/C++ reserved word. " + + "Changing generated name to \"" + name + "_\"."); + } + else + { + System.out.println("WARNING: Found method \"" + name + + "\" in class \"" + className + + "\", which is a C/C++ reserved word. " + + "Changing generated method name to \"" + name + "_\"."); + } + return name + "_"; } - return methodName; + return name; } private String setRef(String codeType) diff --git a/gentools/org/apache/qpid/gentools/Generator.java b/gentools/org/apache/qpid/gentools/Generator.java index 76f78ebb41..0e1df9640a 100644 --- a/gentools/org/apache/qpid/gentools/Generator.java +++ b/gentools/org/apache/qpid/gentools/Generator.java @@ -43,6 +43,7 @@ public abstract class Generator implements LanguageConverter protected AmqpVersionSet globalVersionSet; protected AmqpDomainMap globalDomainMap; + protected AmqpConstantSet globalConstantSet; protected AmqpModel model; protected int generatedFileCounter; @@ -71,6 +72,16 @@ public abstract class Generator implements LanguageConverter { return globalDomainMap; } + + public void setConstantSet(AmqpConstantSet constantSet) + { + this.globalConstantSet = constantSet; + } + + public AmqpConstantSet getConstantSet() + { + return globalConstantSet; + } public void setModel(AmqpModel model) { @@ -135,17 +146,22 @@ public abstract class Generator implements LanguageConverter AmqpField field, AmqpVersion version) throws AmqpTemplateException; - abstract protected void processClassList(StringBuffer sb, int tokStart, int tokEnd, AmqpModel model) + abstract protected void processClassList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpModel model) throws AmqpTemplateException, AmqpTypeMappingException; - abstract protected void processMethodList(StringBuffer sb, int tokStart, int tokEnd, AmqpClass thisClass) + abstract protected void processMethodList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpClass thisClass) throws AmqpTemplateException, AmqpTypeMappingException; abstract protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, AmqpFieldMap fieldMap, AmqpVersion version) throws AmqpTypeMappingException, AmqpTemplateException, IllegalAccessException, InvocationTargetException; - + + abstract protected void processConstantList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpConstantSet constantSet) + throws AmqpTemplateException, AmqpTypeMappingException; public void generate(File genDir) throws TargetDirectoryException, IOException, AmqpTypeMappingException, @@ -300,6 +316,10 @@ public abstract class Generator implements LanguageConverter (method == null ? thisClass.fieldMap : method.fieldMap), version); } + else if (listToken.compareTo("TLIST") == 0) + { + processConstantList(sb, lstart, lend + 1, globalConstantSet); + } else { throw new AmqpTemplateException("Unknown list token \"%{" + listToken + diff --git a/gentools/org/apache/qpid/gentools/JavaGenerator.java b/gentools/org/apache/qpid/gentools/JavaGenerator.java index 82eb97ac6f..6942dcb870 100644 --- a/gentools/org/apache/qpid/gentools/JavaGenerator.java +++ b/gentools/org/apache/qpid/gentools/JavaGenerator.java @@ -27,7 +27,8 @@ import java.util.TreeMap; public class JavaGenerator extends Generator { - static String cr = Utils.lineSeparator; + private static String cr = Utils.lineSeparator; + private enum OutputTypes { OUTPUT_STRING, OUTPUT_INTEGER, OUTPUT_DOUBLE; }; private class DomainInfo { @@ -471,15 +472,16 @@ public class JavaGenerator extends Generator } @Override - protected void processClassList(StringBuffer sb, int tokStart, int tokEnd, AmqpModel model) + protected void processClassList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpModel model) throws AmqpTemplateException, AmqpTypeMappingException { String codeSnippet; - int lend = sb.indexOf(cr, tokStart) + 1; // Include cr at end of line - String tline = sb.substring(tokEnd, lend); // Line excluding line marker, including cr - int tokxStart = tline.indexOf('$'); - String token = tline.substring(tokxStart).trim(); - sb.delete(tokStart, lend); + int lend = sb.indexOf(cr, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); if (token.compareTo("${reg_map_put_method}") == 0) { @@ -491,19 +493,20 @@ public class JavaGenerator extends Generator throw new AmqpTemplateException("Template token " + token + " unknown."); } - sb.insert(tokStart, codeSnippet); + sb.insert(listMarkerStartIndex, codeSnippet); } @Override - protected void processMethodList(StringBuffer sb, int tokStart, int tokEnd, AmqpClass thisClass) + protected void processMethodList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpClass thisClass) throws AmqpTemplateException, AmqpTypeMappingException { String codeSnippet; - int lend = sb.indexOf(cr, tokStart) + 1; // Include cr at end of line - String tline = sb.substring(tokEnd, lend); // Line excluding line marker, including cr - int tokxStart = tline.indexOf('$'); - String token = tline.substring(tokxStart).trim(); - sb.delete(tokStart, lend); + int lend = sb.indexOf(cr, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); //TODO - we don't have any cases of this (yet). if (token.compareTo("${???}") == 0) @@ -515,7 +518,7 @@ public class JavaGenerator extends Generator throw new AmqpTemplateException("Template token " + token + " unknown."); } - sb.insert(tokStart, codeSnippet); + sb.insert(listMarkerStartIndex, codeSnippet); } @Override @@ -527,8 +530,8 @@ public class JavaGenerator extends Generator String codeSnippet; int lend = sb.indexOf(cr, listMarkerStartIndex) + 1; // Include cr at end of line String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr - int tokxStart = tline.indexOf('$'); - String token = tline.substring(tokxStart).trim(); + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); sb.delete(listMarkerStartIndex, lend); // Field declarations - common to MethodBody and PropertyContentHeader classes @@ -625,7 +628,34 @@ public class JavaGenerator extends Generator } sb.insert(listMarkerStartIndex, codeSnippet); } - + + @Override + protected void processConstantList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpConstantSet constantSet) + throws AmqpTemplateException, AmqpTypeMappingException + + { + String codeSnippet; + int lend = sb.indexOf(cr, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + if (token.compareTo("${const_get_method}") == 0) + { + codeSnippet = generateConstantGetMethods(constantSet, 4, 4); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + + sb.insert(listMarkerStartIndex, codeSnippet); + } + + // === Protected and private helper functions unique to Java implementation === // Methods used for generation of code snippets called from the field map parsers @@ -752,7 +782,149 @@ public class JavaGenerator extends Generator } throw new Exception("Index not found"); } - + + // Methods for AmqpConstants class + + protected String generateConstantGetMethods(AmqpConstantSet constantSet, + int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + Iterator<AmqpConstant> cItr = constantSet.iterator(); + while (cItr.hasNext()) + { + AmqpConstant constant = cItr.next(); + if (constant.isVersionConsistent(globalVersionSet)) + { + // return a constant + String value = constant.firstKey(); + sb.append(indent + "public static String " + constant.name + "() { return \"" + + constant.firstKey() + "\"; }" + cr); + if (Utils.containsOnlyDigits(value)) + { + sb.append(indent + "public static int " + constant.name + "AsInt() { return " + + constant.firstKey() + "; }" + cr); + } + if (Utils.containsOnlyDigitsAndDecimal(value)) + { + sb.append(indent + "public static double " + constant.name + "AsDouble() { return (double)" + + constant.firstKey() + "; }" + cr); + } + sb.append(cr); + } + else + { + // return value from version map + sb.append(generateVersionDependentGet(constant, OutputTypes.OUTPUT_STRING, indentSize, tabSize)); + sb.append(generateVersionDependentGet(constant, OutputTypes.OUTPUT_INTEGER, indentSize, tabSize)); + sb.append(generateVersionDependentGet(constant, OutputTypes.OUTPUT_DOUBLE, indentSize, tabSize)); + sb.append(cr); + } + } + return sb.toString(); + } + + protected String generateVersionDependentGet(AmqpConstant constant, OutputTypes outType, int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + String methodNameSuffix = ""; + String methodReturnType = "String"; + if (outType == OutputTypes.OUTPUT_INTEGER) + { + methodNameSuffix = "AsInt"; + methodReturnType = "int"; + } + else if (outType == OutputTypes.OUTPUT_DOUBLE) + { + methodNameSuffix = "AsDouble"; + methodReturnType = "double"; + } + sb.append(indent + "public static " + methodReturnType + " " + constant.name + + methodNameSuffix + "(byte major, byte minor) throws AMQProtocolVersionException" + cr); + sb.append(indent + "{" + cr); + boolean first = true; + Iterator<String> sItr = constant.keySet().iterator(); + while (sItr.hasNext()) + { + String value = sItr.next(); + AmqpVersionSet versionSet = constant.get(value); + sb.append(indent + tab + (first ? "" : "else ") + "if (" + + generateVersionCheck(versionSet) + ")" + cr); + sb.append(indent + tab + "{" + cr); + if (outType == OutputTypes.OUTPUT_STRING) + { + sb.append(indent + tab + tab + "return \"" + value + "\";" + cr); + } + else if (outType == OutputTypes.OUTPUT_INTEGER) + { + if (Utils.containsOnlyDigits(value)) + { + sb.append(indent + tab + tab + "return " + value + ";" + cr); + } + else + { + sb.append(generateConstantDeclarationException(constant.name, outType, + indentSize + (2*tabSize), tabSize)); + } + } + else if (outType == OutputTypes.OUTPUT_DOUBLE) + { + if (Utils.containsOnlyDigitsAndDecimal(value)) + { + sb.append(indent + tab + tab + "return (double)" + value + ";" + cr); + } + else + { + sb.append(generateConstantDeclarationException(constant.name, outType, + indentSize + (2*tabSize), tabSize)); + } + } + sb.append(indent + tab + "}" + cr); + first = false; + } + sb.append(indent + tab + "else" + cr); + sb.append(indent + tab + "{" + cr); + sb.append(indent + tab + tab + "throw new AMQProtocolVersionException(\"Constant \\\"" + + constant.name + "\\\" \" +" + cr); + sb.append(indent + tab + tab + tab + + "\"undefined for AMQP version \" + major + \"-\" + minor + \".\");" + cr); + sb.append(indent + tab + "}" + cr); + sb.append(indent + "}" + cr); + return sb.toString(); + } + + protected String generateConstantDeclarationException(String name, OutputTypes outType, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + String typeStr; + switch (outType) + { + case OUTPUT_STRING: + typeStr = "a String"; + break; + case OUTPUT_INTEGER: + typeStr = "an integer"; + break; + case OUTPUT_DOUBLE: + typeStr = "a double"; + break; + default: + typeStr = "*ERROR*"; + } + sb.append(indent + "throw new AMQProtocolVersionException(\"Constant \\\"" + + name + "\\\" \" +" + cr); + sb.append(indent + tab + "\"is not " + typeStr + + " type for AMQP version \" + major + \"-\" + minor + \".\");" + cr); + return sb.toString(); + } + // Methods for MessageBody classes protected String generateMbGetMethod(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) @@ -1484,7 +1656,7 @@ public class JavaGenerator extends Generator sb.append(" || "); if (versionArray.length > 1) sb.append("("); - sb.append("major == " + versionArray[i].getMajor() + " && minor == " + + sb.append("major == (byte)" + versionArray[i].getMajor() + " && minor == (byte)" + versionArray[i].getMinor()); if (versionArray.length > 1) sb.append(")"); diff --git a/gentools/org/apache/qpid/gentools/LanguageConverter.java b/gentools/org/apache/qpid/gentools/LanguageConverter.java index b9a2c81aa3..5ff7c51008 100644 --- a/gentools/org/apache/qpid/gentools/LanguageConverter.java +++ b/gentools/org/apache/qpid/gentools/LanguageConverter.java @@ -21,6 +21,9 @@ public interface LanguageConverter { public void setDomainMap(AmqpDomainMap domainMap); public AmqpDomainMap getDomainMap(); + + public void setConstantSet(AmqpConstantSet constantSet); + public AmqpConstantSet getConstantSet(); public void setModel(AmqpModel model); public AmqpModel getModel(); diff --git a/gentools/org/apache/qpid/gentools/Main.java b/gentools/org/apache/qpid/gentools/Main.java index 2c288786c9..0c38c16319 100644 --- a/gentools/org/apache/qpid/gentools/Main.java +++ b/gentools/org/apache/qpid/gentools/Main.java @@ -34,6 +34,7 @@ public class Main private DocumentBuilder docBuilder; private AmqpVersionSet versionSet; private Generator generator; + private AmqpConstantSet constants; private AmqpDomainMap domainMap; private AmqpModel model; @@ -64,25 +65,29 @@ public class Main // *** C++ generation *** System.out.println("C++ generation mode."); generator = new CppGenerator(versionSet); + constants = new AmqpConstantSet(generator); domainMap = new AmqpDomainMap(generator); model = new AmqpModel(generator); - modelTemplateFiles = new File[]{ + modelTemplateFiles = new File[] + { new File("templ.cpp/AMQP_ServerOperations.h.tmpl"), new File("templ.cpp/AMQP_ClientOperations.h.tmpl"), new File("templ.cpp/AMQP_ServerProxy.h.tmpl"), new File("templ.cpp/AMQP_ClientProxy.h.tmpl"), new File("templ.cpp/AMQP_ServerProxy.cpp.tmpl"), new File("templ.cpp/AMQP_ClientProxy.cpp.tmpl"), - new File("templ.cpp/AMQP_ServerHandlerImpl.h.tmpl"), - new File("templ.cpp/AMQP_ClientHandlerImpl.h.tmpl"), - new File("templ.cpp/AMQP_ServerHandlerImpl.cpp.tmpl"), - new File("templ.cpp/AMQP_ClientHandlerImpl.cpp.tmpl"), - new File("templ.cpp/amqp_methods.h.tmpl"), - new File("templ.cpp/amqp_methods.cpp.tmpl") - }; - methodTemplateFiles = new File[]{ + new File("templ.cpp/AMQP_Constants.h.tmpl") +// new File("templ.cpp/AMQP_ServerHandlerImpl.h.tmpl"), +// new File("templ.cpp/AMQP_ClientHandlerImpl.h.tmpl"), +// new File("templ.cpp/AMQP_ServerHandlerImpl.cpp.tmpl"), +// new File("templ.cpp/AMQP_ClientHandlerImpl.cpp.tmpl"), +// new File("templ.cpp/amqp_methods.h.tmpl"), +// new File("templ.cpp/amqp_methods.cpp.tmpl") + }; + methodTemplateFiles = new File[] + { new File("templ.cpp/MethodBodyClass.h.tmpl") - }; + }; outDir += ".cpp"; } else if (args[0].compareToIgnoreCase("-j") == 0) @@ -90,14 +95,22 @@ public class Main // *** Java generation *** System.out.println("Java generation mode."); generator = new JavaGenerator(versionSet); + constants = new AmqpConstantSet(generator); domainMap = new AmqpDomainMap(generator); model = new AmqpModel(generator); modelTemplateFiles = new File[] - { new File("templ.java/MethodRegistryClass.tmpl") }; + { + new File("templ.java/MethodRegistryClass.tmpl"), + new File("templ.java/AmqpConstantsClass.tmpl") + }; classTemplateFiles = new File[] - { new File("templ.java/PropertyContentHeaderClass.tmpl") }; + { + new File("templ.java/PropertyContentHeaderClass.tmpl") + }; methodTemplateFiles = new File[] - { new File("templ.java/MethodBodyClass.tmpl") }; + { + new File("templ.java/MethodBodyClass.tmpl") + }; outDir += ".java"; } else @@ -131,9 +144,12 @@ public class Main versionSet.add(version); // 1c. Extract domains - domainMap.addFromNode(amqpNode, 0, version); + constants.addFromNode(amqpNode, 0, version); + + // 1d. Extract domains + domainMap.addFromNode(amqpNode, 0, version); - // 1d. Extract class/method/field heirarchy + // 1e. Extract class/method/field heirarchy model.addFromNode(amqpNode, 0, version); } else @@ -143,7 +159,9 @@ public class Main // System.out.println(); // System.out.println("*** Debug output ***"); // System.out.println(); -// versionSet.print(System.out, 0, 2); + constants.print(System.out, 0, 2); +// System.out.println(); +// versionSet.print(System.out, 0, 2); // System.out.println(); // domainMap.print(System.out, 0, 2); // System.out.println(); diff --git a/gentools/org/apache/qpid/gentools/Utils.java b/gentools/org/apache/qpid/gentools/Utils.java index cdbc6358e6..deb8283426 100644 --- a/gentools/org/apache/qpid/gentools/Utils.java +++ b/gentools/org/apache/qpid/gentools/Utils.java @@ -37,11 +37,13 @@ public class Utils public final static String ATTRIBUTE_CONTENT = "content"; public final static String ATTRIBUTE_HANDLER = "handler"; public final static String ATTRIBUTE_DOMAIN = "domain"; + public final static String ATTRIBUTE_VALUE = "value"; public final static String ATTRIBUTE_TYPE = "type"; // For compatibility with AMQP 8.0 public final static String ELEMENT_AMQP = "amqp"; public final static String ELEMENT_CHASSIS = "chassis"; public final static String ELEMENT_CLASS = "class"; + public final static String ELEMENT_CONSTANT = "constant"; public final static String ELEMENT_DOMAIN = "domain"; public final static String ELEMENT_METHOD = "method"; public final static String ELEMENT_FIELD = "field"; @@ -91,6 +93,15 @@ public class Utils return sb.toString(); } + public static String firstLower(String str) + { + if (!Character.isUpperCase(str.charAt(0))) + return str; + StringBuffer sb = new StringBuffer(str); + sb.setCharAt(0, Character.toLowerCase(str.charAt(0))); + return sb.toString(); + } + public static String createSpaces(int cnt) { StringBuffer sb = new StringBuffer(); @@ -98,4 +109,34 @@ public class Utils sb.append(' '); return sb.toString(); } + + public static boolean containsOnlyDigits(String str) + { + boolean foundNonDigit = false; + for (int i=0; i<str.length() && !foundNonDigit; i++) + { + if (!Character.isDigit(str.charAt(i))) + { + foundNonDigit = true; + } + } + return !foundNonDigit; + } + + public static boolean containsOnlyDigitsAndDecimal(String str) + { + boolean foundNonDigit = false; + int decimalCntr = 0; + for (int i=0; i<str.length() && !foundNonDigit && decimalCntr<2; i++) + { + char ch = str.charAt(i); + if (!(Character.isDigit(ch) || ch == '.')) + { + foundNonDigit = true; + } + else if (ch == '.') + decimalCntr++; + } + return !foundNonDigit && decimalCntr<2; + } } diff --git a/gentools/templ.cpp/AMQP_ClientOperations.h.tmpl b/gentools/templ.cpp/AMQP_ClientOperations.h.tmpl index b8010896a7..28c9831105 100644 --- a/gentools/templ.cpp/AMQP_ClientOperations.h.tmpl +++ b/gentools/templ.cpp/AMQP_ClientOperations.h.tmpl @@ -26,7 +26,6 @@ #ifndef _AMQP_ClientOperations_ #define _AMQP_ClientOperations_ -#include "AMQP_Constants.h" #include "qpid/framing/FieldTable.h" namespace qpid { @@ -35,20 +34,28 @@ namespace framing { class AMQP_ClientOperations { private: - u_int8_t major; - u_int8_t minor; + ProtocolVersion version; public: - AMQP_ClientOperations(u_int8_t major, u_int8_t minor) : major(major), minor(minor) {} + AMQP_ClientOperations(u_int8_t major, u_int8_t minor) : version(major, minor) {} + AMQP_ClientOperations(ProtocolVersion version) : version(version) {} virtual ~AMQP_ClientOperations() {} - inline u_int8_t getMajor() { return major; } - inline u_int8_t getMinor() { return minor; } - inline isVersion(u_int8_t _major, u_int8_t _minor) + inline u_int8_t getMajor() const { return version.getMajor(); } + inline u_int8_t getMinor() const { return version.getMinor(); } + inline const ProtocolVersion& getVersion() const { return version; } + inline isVersion(u_int8_t _major, u_int8_t _minor) const { - return major == _major && minor == _minor; + return version.equals(_major, _minor); + } + inline isVersion(ProtocolVersion& _version) const + { + return version.equals(_version); } + // Include framing constant declarations + #include "AMQP_Constants.h" + // Method handler get methods %{CLIST} ${coh_method_handler_get_method} diff --git a/gentools/templ.cpp/AMQP_ClientProxy.cpp.tmpl b/gentools/templ.cpp/AMQP_ClientProxy.cpp.tmpl index 7ecd3e0a7e..69c7fd6840 100644 --- a/gentools/templ.cpp/AMQP_ClientProxy.cpp.tmpl +++ b/gentools/templ.cpp/AMQP_ClientProxy.cpp.tmpl @@ -23,23 +23,23 @@ %{VLIST} * ${major}-${minor} */ +#include <sstream> #include "AMQP_ClientProxy.h" namespace qpid { namespace framing { -AMQP_ClientProxy::AMQP_ClientProxy(OutputHandler* _out) : - out(_out) -{CLIST} {cpc_constructor_initializer} +AMQP_ClientProxy::AMQP_ClientProxy(OutputHandler* out, u_int8_t major, u_int8_t minor) : +%{CLIST} ${cpc_constructor_initializer} {} // Inner class instance get methods -{CLIST} {cpc_inner_class_get_method} +%{CLIST} ${cpc_inner_class_get_method} // Inner class implementation -{CLIST} {cpc_inner_class_impl} +%{CLIST} ${cpc_inner_class_impl} } /* namespace framing */ } /* namespace qpid */ diff --git a/gentools/templ.cpp/AMQP_ClientProxy.h.tmpl b/gentools/templ.cpp/AMQP_ClientProxy.h.tmpl index 82ba5391d5..15610ad438 100644 --- a/gentools/templ.cpp/AMQP_ClientProxy.h.tmpl +++ b/gentools/templ.cpp/AMQP_ClientProxy.h.tmpl @@ -35,17 +35,26 @@ namespace framing { class AMQP_ClientProxy : virtual public AMQP_ClientOperations { - public: - AMQP_ClientProxy(OutputHandler* _out); - virtual ~AMQP_ClientProxy() {}; +private: + OutputHandler* out; + u_int8_t major; + u_int8_t minor; // Inner class instances -{CLIST} {cph_inner_class_get_method} +%{CLIST} ${cph_inner_class_instance} + +public: + AMQP_ClientProxy(OutputHandler* out, u_int8_t major, u_int8_t minor); + virtual ~AMQP_ClientProxy() {} + + // Inner class instance get methods + +%{CLIST} ${cph_inner_class_get_method} // Inner class definitions -{CLIST} {cph_inner_class_impl} +%{CLIST} ${cph_inner_class_defn} }; /* class AMQP_ClientProxy */ diff --git a/gentools/templ.cpp/AMQP_Constants.h.tmpl b/gentools/templ.cpp/AMQP_Constants.h.tmpl new file mode 100644 index 0000000000..7b7ba9f27b --- /dev/null +++ b/gentools/templ.cpp/AMQP_Constants.h.tmpl @@ -0,0 +1,35 @@ +&{AMQP_Constants.h} +/** +* +* Copyright (c) 2006 The Apache Software Foundation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*/ + +/* + * This file is auto-generated by ${GENERATOR} - do not modify. + * Supported AMQP versions: +%{VLIST} * ${major}-${minor} + */ + // NOTE: This file is intended to be included within the class structure of both + // the client and server operations classes. + + // Constant declarations for constants that change by version + +%{TLIST} ${ch_static_const_decl} + + // Constant getValue methods + +%{TLIST} ${ch_get_value_method} +
\ No newline at end of file diff --git a/gentools/templ.cpp/AMQP_ServerOperations.h.tmpl b/gentools/templ.cpp/AMQP_ServerOperations.h.tmpl index b1d1c98b25..b600979047 100644 --- a/gentools/templ.cpp/AMQP_ServerOperations.h.tmpl +++ b/gentools/templ.cpp/AMQP_ServerOperations.h.tmpl @@ -26,7 +26,6 @@ #ifndef _AMQP_ServerOperations_ #define _AMQP_ServerOperations_ -#include "AMQP_Constants.h" #include "qpid/framing/FieldTable.h" namespace qpid { @@ -35,19 +34,27 @@ namespace framing { class AMQP_ServerOperations { private: - u_int8_t major; - u_int8_t minor; + ProtocolVersion version; public: - AMQP_ServerOperations(u_int8_t major, u_int8_t minor) : major(major), minor(minor) {} + AMQP_ServerOperations(u_int8_t major, u_int8_t minor) : version(major, minor) {} + AMQP_ServerOperations(ProtocolVersion version) : version(version) {} virtual ~AMQP_ServerOperations() {} - inline u_int8_t getMajor() { return major; } - inline u_int8_t getMinor() { return minor; } - inline isVersion(u_int8_t _major, u_int8_t _minor) + inline u_int8_t getMajor() const { return version.getMajor(); } + inline u_int8_t getMinor() const { return version.getMinor(); } + inline const ProtocolVersion& getVersion() const { return version; } + inline isVersion(u_int8_t _major, u_int8_t _minor) const { - return major == _major && minor == _minor; + return version.equals(_major, _minor); } + inline isVersion(ProtocolVersion& _version) const + { + return version.equals(_version); + } + + // Include framing constant declarations + #include "AMQP_Constants.h" // Method handler get methods diff --git a/gentools/templ.cpp/AMQP_ServerProxy.cpp.tmpl b/gentools/templ.cpp/AMQP_ServerProxy.cpp.tmpl index 8996f4a41c..0855bc2026 100644 --- a/gentools/templ.cpp/AMQP_ServerProxy.cpp.tmpl +++ b/gentools/templ.cpp/AMQP_ServerProxy.cpp.tmpl @@ -23,23 +23,23 @@ %{VLIST} * ${major}-${minor} */ +#include <sstream> #include "AMQP_ServerProxy.h" namespace qpid { namespace framing { -AMQP_ServerProxy::AMQP_ServerProxy(OutputHandler* _out) : - out(_out) -{CLIST} {spc_constructor_initializer} +AMQP_ServerProxy::AMQP_ServerProxy(OutputHandler* out, u_int8_t major, u_int8_t minor) : +%{CLIST} ${spc_constructor_initializer} {} // Inner class instance get methods -{CLIST} {spc_inner_class_get_method} +%{CLIST} ${spc_inner_class_get_method} // Inner class implementation -{CLIST} {spc_inner_class_impl} +%{CLIST} ${spc_inner_class_impl} } /* namespace framing */ } /* namespace qpid */ diff --git a/gentools/templ.cpp/AMQP_ServerProxy.h.tmpl b/gentools/templ.cpp/AMQP_ServerProxy.h.tmpl index a1bc3cbc9f..dd72fa17e4 100644 --- a/gentools/templ.cpp/AMQP_ServerProxy.h.tmpl +++ b/gentools/templ.cpp/AMQP_ServerProxy.h.tmpl @@ -35,19 +35,26 @@ namespace framing { class AMQP_ServerProxy : virtual public AMQP_ServerOperations { - OutputHandler* out; - - public: - AMQP_ServerProxy(OutputHandler* _out); - virtual ~AMQP_ServerProxy() {} +private: + OutputHandler* out; + u_int8_t major; + u_int8_t minor; // Inner class instances -{CLIST} {sph_inner_class_get_method} +%{CLIST} ${sph_inner_class_instance} + +public: + AMQP_ServerProxy(OutputHandler* out, u_int8_t major, u_int8_t minor); + virtual ~AMQP_ServerProxy() {} + + // Inner class instance get methods + +%{CLIST} ${sph_inner_class_get_method} // Inner class definitions -{CLIST} {sph_inner_class_impl} +%{CLIST} ${sph_inner_class_defn} }; /* class AMQP_ServerProxy */ diff --git a/gentools/templ.java/AmqpConstantsClass.tmpl b/gentools/templ.java/AmqpConstantsClass.tmpl new file mode 100644 index 0000000000..ba41c80b42 --- /dev/null +++ b/gentools/templ.java/AmqpConstantsClass.tmpl @@ -0,0 +1,34 @@ +&{AmqpConstants.java} +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * This file is auto-generated by ${GENERATOR} - do not modify. + * Supported AMQP versions: +%{VLIST} * ${major}-${minor} + */ + +package org.apache.qpid.framing; + +class AmqpConstants +{ + // Constant getValue methods + +%{TLIST} ${const_get_method} + +} diff --git a/gentools/xml-src/amqp-0.10.test.xml b/gentools/xml-src/amqp-0.10.test.xml index e0198f8e5a..5d3d80648b 100644 --- a/gentools/xml-src/amqp-0.10.test.xml +++ b/gentools/xml-src/amqp-0.10.test.xml @@ -287,7 +287,7 @@ </doc> </constant> - <constant name = "internal-error" value = "541" class = "hard-error"> + <constant name = "internal-error" value = "545" class = "hard-error"> <doc> The server could not complete the method because of an internal error. The server may require intervention by an operator in order to resume @@ -295,6 +295,10 @@ </doc> </constant> + <constant name = "test-double" value = "3.141592654"/> + <constant name = "test-str1" value = "hello, world!"/> + <constant name = "test-str2" value = "1.2.3.4"/> + <!-- ====================================================== == DOMAIN TYPES diff --git a/gentools/xml-src/amqp-0.9.test.xml b/gentools/xml-src/amqp-0.9.test.xml index e41b1a92c9..e12e9c787a 100644 --- a/gentools/xml-src/amqp-0.9.test.xml +++ b/gentools/xml-src/amqp-0.9.test.xml @@ -295,6 +295,8 @@ </doc> </constant> + <constant name = "test-str2" value = "1.2.3.3"/> + <!-- ====================================================== == DOMAIN TYPES |
