summaryrefslogtreecommitdiff
path: root/gentools/org
diff options
context:
space:
mode:
authorKim van der Riet <kpvdr@apache.org>2006-10-18 18:13:01 +0000
committerKim van der Riet <kpvdr@apache.org>2006-10-18 18:13:01 +0000
commit4bddf9b38cb29b2528a66305ca6acfd5f09067cc (patch)
tree738a5724cf701c632ccda1435536adb1ab5a4700 /gentools/org
parent5810d2bbc60c82feb5dec60b40e9cb14b64bca9c (diff)
downloadqpid-python-4bddf9b38cb29b2528a66305ca6acfd5f09067cc.tar.gz
Initial checkin of code generator (Java only at this stage) which allows for the simultaneous support of multiple AMQP versions. This is a temporary location, for comment and evaluation purposes only. This generator is NOT integrated with the rest of the QPID project; it is intended for stand-alone use only for now.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@465322 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'gentools/org')
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpClass.java119
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpClassMap.java26
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpDomain.java80
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpDomainMap.java116
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpField.java129
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpFieldMap.java271
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpMethod.java97
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpMethodMap.java26
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpModel.java74
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpOrdinalMap.java9
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpParseException.java27
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpTemplateException.java10
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpTypeMappingException.java27
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpVersion.java54
-rw-r--r--gentools/org/apache/qpid/gentools/AmqpVersionSet.java31
-rw-r--r--gentools/org/apache/qpid/gentools/CppGenerator.java217
-rw-r--r--gentools/org/apache/qpid/gentools/Generator.java402
-rw-r--r--gentools/org/apache/qpid/gentools/JavaGenerator.java1451
-rw-r--r--gentools/org/apache/qpid/gentools/LanguageConverter.java33
-rw-r--r--gentools/org/apache/qpid/gentools/Main.java168
-rw-r--r--gentools/org/apache/qpid/gentools/NodeAware.java42
-rw-r--r--gentools/org/apache/qpid/gentools/Printable.java25
-rw-r--r--gentools/org/apache/qpid/gentools/TargetDirectoryException.java27
-rw-r--r--gentools/org/apache/qpid/gentools/Utils.java210
24 files changed, 3671 insertions, 0 deletions
diff --git a/gentools/org/apache/qpid/gentools/AmqpClass.java b/gentools/org/apache/qpid/gentools/AmqpClass.java
new file mode 100644
index 0000000000..4ded7db94a
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpClass.java
@@ -0,0 +1,119 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.io.PrintStream;
+import java.util.Iterator;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class AmqpClass implements Printable, NodeAware
+{
+ public LanguageConverter converter;
+ public AmqpVersionSet versionList;
+ public AmqpFieldMap fieldMap;
+ public AmqpMethodMap methodMap;
+ public String name;
+ public AmqpOrdinalMap indexMap;
+
+ public AmqpClass(String name, LanguageConverter converter)
+ {
+ this.name = name;
+ this.converter = converter;
+ versionList = new AmqpVersionSet();
+ fieldMap = new AmqpFieldMap();
+ methodMap = new AmqpMethodMap();
+ indexMap = new AmqpOrdinalMap();
+ }
+
+ public void addFromNode(Node classNode, int ordinal, AmqpVersion version)
+ throws AmqpParseException, AmqpTypeMappingException
+ {
+ versionList.add(version);
+ int index = Utils.getNamedIntegerAttribute(classNode, "index");
+ AmqpVersionSet versionSet = indexMap.get(index);
+ if (versionSet != null)
+ versionSet.add(version);
+ else
+ {
+ versionSet = new AmqpVersionSet();
+ versionSet.add(version);
+ indexMap.put(index, versionSet);
+ }
+ NodeList nList = classNode.getChildNodes();
+ int fieldCntr = 0;
+ int methodCntr = 0;
+ for (int i=0; i<nList.getLength(); i++)
+ {
+ Node child = nList.item(i);
+ if (child.getNodeName().compareTo(Utils.ELEMENT_FIELD) == 0)
+ {
+ String fieldName = converter.prepareDomainName(Utils.getNamedAttribute(child, Utils.ATTRIBUTE_NAME));
+ AmqpField thisField = fieldMap.get(fieldName);
+ if (thisField == null)
+ {
+ thisField = new AmqpField(fieldName, converter);
+ fieldMap.put(fieldName, thisField);
+ }
+ thisField.addFromNode(child, fieldCntr, version);
+ fieldCntr++;
+ }
+ else if (child.getNodeName().compareTo(Utils.ELEMENT_METHOD) == 0)
+ {
+ String methodName = converter.prepareMethodName(Utils.getNamedAttribute(child, Utils.ATTRIBUTE_NAME));
+ AmqpMethod thisMethod = methodMap.get(methodName);
+ if (thisMethod == null)
+ {
+ thisMethod = new AmqpMethod(methodName, converter);
+ methodMap.put(methodName, thisMethod);
+ }
+ thisMethod.addFromNode(child, methodCntr++, version);
+ }
+ }
+ }
+
+ public void print(PrintStream out, int marginSize, int tabSize)
+ {
+ String margin = Utils.createSpaces(marginSize);
+ String tab = Utils.createSpaces(tabSize);
+ out.println(margin + "[C] " + name + ": " + versionList);
+
+ Iterator<Integer> iItr = indexMap.keySet().iterator();
+ while (iItr.hasNext())
+ {
+ int index = iItr.next();
+ AmqpVersionSet indexVersionSet = indexMap.get(index);
+ out.println(margin + tab + "[I] " + index + indexVersionSet);
+ }
+
+ Iterator<String> sItr = fieldMap.keySet().iterator();
+ while (sItr.hasNext())
+ {
+ AmqpField thisField = fieldMap.get(sItr.next());
+ thisField.print(out, marginSize + tabSize, tabSize);
+ }
+
+ sItr = methodMap.keySet().iterator();
+ while (sItr.hasNext())
+ {
+ AmqpMethod thisMethod = methodMap.get(sItr.next());
+ thisMethod.print(out, marginSize + tabSize, tabSize);
+ }
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpClassMap.java b/gentools/org/apache/qpid/gentools/AmqpClassMap.java
new file mode 100644
index 0000000000..e86495f27e
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpClassMap.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.util.TreeMap;
+
+@SuppressWarnings("serial")
+public class AmqpClassMap extends TreeMap<String, AmqpClass>
+{
+
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpDomain.java b/gentools/org/apache/qpid/gentools/AmqpDomain.java
new file mode 100644
index 0000000000..e313772a83
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpDomain.java
@@ -0,0 +1,80 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.io.PrintStream;
+import java.util.Iterator;
+import java.util.TreeMap;
+
+@SuppressWarnings("serial")
+public class AmqpDomain extends TreeMap<String, AmqpVersionSet> implements Printable
+{
+ public String domainName;
+
+ public AmqpDomain(String domainName)
+ {
+ this.domainName = domainName;
+ }
+
+ public void addDomain(String domainType, AmqpVersion version) throws AmqpParseException
+ {
+ AmqpVersionSet versionSet = get(domainType);
+ if (versionSet == null) // First time, create new entry
+ {
+ versionSet = new AmqpVersionSet();
+ put(domainType, versionSet);
+ }
+ versionSet.add(version);
+ }
+
+ public String getDomainType(AmqpVersion v)
+ throws AmqpTypeMappingException
+ {
+ Iterator<String> i = keySet().iterator();
+ while (i.hasNext())
+ {
+ String type = i.next();
+ AmqpVersionSet vs = get(type);
+ if (vs.contains(v))
+ return type;
+ } throw new AmqpTypeMappingException("Unable to find version " + v + ".");
+ }
+
+ public boolean hasVersion(String type, AmqpVersion v)
+ {
+ AmqpVersionSet vs = get(type);
+ if (vs == null)
+ return false;
+ return vs.contains(v);
+ }
+
+ public void print(PrintStream out, int marginSize, int tabSize)
+ {
+ String margin = Utils.createSpaces(marginSize);
+ String tab = Utils.createSpaces(tabSize);
+ out.println(margin + domainName + ":");
+
+ Iterator<String> i = keySet().iterator();
+ while (i.hasNext())
+ {
+ String type = i.next();
+ AmqpVersionSet vs = get(type);
+ out.println(margin + tab + type + " : " + vs.toString());
+ }
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpDomainMap.java b/gentools/org/apache/qpid/gentools/AmqpDomainMap.java
new file mode 100644
index 0000000000..88cc9a17b3
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpDomainMap.java
@@ -0,0 +1,116 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.io.PrintStream;
+import java.util.Iterator;
+import java.util.TreeMap;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+@SuppressWarnings("serial")
+public class AmqpDomainMap extends TreeMap<String, AmqpDomain> implements Printable, NodeAware
+{
+ public LanguageConverter converter;
+
+ public AmqpDomainMap(LanguageConverter converter)
+ {
+ this.converter = converter;
+ this.converter.setDomainMap(this);
+ }
+
+ public void addFromNode(Node n, int o, AmqpVersion v)
+ throws AmqpParseException, AmqpTypeMappingException
+ {
+ NodeList nl = n.getChildNodes();
+ for (int i=0; i<nl.getLength(); i++)
+ {
+ Node c = nl.item(i);
+ // All versions 0.9 and greater use <domain> for all domains
+ if (c.getNodeName().compareTo(Utils.ELEMENT_DOMAIN) == 0)
+ {
+ String domainName = converter.prepareDomainName(Utils.getNamedAttribute(c, Utils.ATTRIBUTE_NAME));
+ String type = Utils.getNamedAttribute(c, Utils.ATTRIBUTE_TYPE);
+ AmqpDomain thisDomain = get(domainName);
+ if (thisDomain == null)
+ {
+ thisDomain = new AmqpDomain(domainName);
+ put(domainName, thisDomain);
+ }
+ thisDomain.addDomain(type, v);
+ }
+ // Version(s) 0.8 and earlier use <domain> for all complex domains and use
+ // attribute <field type=""...> for simple types. Add these simple types to
+ // domain list - but beware of duplicates!
+ else if (c.getNodeName().compareTo(Utils.ELEMENT_FIELD) == 0)
+ {
+ try
+ {
+ String type = converter.prepareDomainName(Utils.getNamedAttribute(c, Utils.ATTRIBUTE_TYPE));
+ AmqpDomain thisDomain = get(type);
+ if (thisDomain == null)
+ {
+ thisDomain = new AmqpDomain(type);
+ put(type, thisDomain);
+ }
+ if (!thisDomain.hasVersion(type, v))
+ thisDomain.addDomain(type, v);
+ }
+ catch (AmqpParseException e) {} // Ignore fields without type attribute
+ }
+ else if (c.getNodeName().compareTo(Utils.ELEMENT_CLASS) == 0 ||
+ c.getNodeName().compareTo(Utils.ELEMENT_METHOD) == 0)
+ {
+ addFromNode(c, 0, v);
+ }
+ }
+ }
+
+ public String getDomainType(String domainName, AmqpVersion v)
+ throws AmqpTypeMappingException
+ {
+ AmqpDomain domain = get(domainName);
+ // For AMQP 8.0, primitive types were not described as domains, so
+ // return itself as the type.
+ if (domain == null)
+ return converter.getDomainType(domainName, v);
+ try
+ {
+ return domain.getDomainType(v);
+ }
+ catch (AmqpTypeMappingException e)
+ {
+ throw new AmqpTypeMappingException("Unable to find domain type for domain \"" + domainName +
+ "\" version " + v + ".");
+ }
+ }
+
+
+ public void print(PrintStream out, int marginSize, int tabSize)
+ {
+ Iterator<String> i = keySet().iterator();
+ out.println(Utils.createSpaces(marginSize) + "Domain Map:");
+ while (i.hasNext())
+ {
+ String domainName = i.next();
+ AmqpDomain domain = get(domainName);
+ domain.print(out, marginSize + tabSize, tabSize);
+ }
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpField.java b/gentools/org/apache/qpid/gentools/AmqpField.java
new file mode 100644
index 0000000000..a46c424887
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpField.java
@@ -0,0 +1,129 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.TreeMap;
+
+import org.w3c.dom.Node;
+
+public class AmqpField implements Printable, NodeAware
+{
+ public LanguageConverter converter;
+ public AmqpVersionSet versionSet;
+ public TreeMap<String, AmqpVersionSet> domainMap;
+ public AmqpOrdinalMap ordinalMap;
+ public String name;
+
+ public AmqpField(String name, LanguageConverter converter)
+ {
+ this.name = name;
+ this.converter = converter;
+ versionSet = new AmqpVersionSet();
+ domainMap = new TreeMap<String, AmqpVersionSet>();
+ ordinalMap = new AmqpOrdinalMap();
+ }
+
+ public void addFromNode(Node fieldNode, int ordinal, AmqpVersion version)
+ throws AmqpParseException, AmqpTypeMappingException
+ {
+ versionSet.add(version);
+ String domainType;
+ // Early versions of the spec (8.0) used the "type" attribute instead of "domain" for some fields.
+ try
+ {
+ domainType = converter.prepareDomainName(Utils.getNamedAttribute(fieldNode, Utils.ATTRIBUTE_DOMAIN));
+ }
+ catch (AmqpParseException e)
+ {
+ domainType = converter.prepareDomainName(Utils.getNamedAttribute(fieldNode, Utils.ATTRIBUTE_TYPE));
+ }
+ AmqpVersionSet thisVersionList = domainMap.get(domainType);
+ if (thisVersionList == null) // First time, create new entry
+ {
+ thisVersionList = new AmqpVersionSet();
+ domainMap.put(domainType, thisVersionList);
+ }
+ thisVersionList.add(version);
+ thisVersionList = ordinalMap.get(ordinal);
+ if (thisVersionList == null) // First time, create new entry
+ {
+ thisVersionList = new AmqpVersionSet();
+ ordinalMap.put(ordinal, thisVersionList);
+ }
+ thisVersionList.add(version);
+ }
+
+ public boolean isCodeTypeConsistent(Generator generator)
+ throws AmqpTypeMappingException
+ {
+ if (domainMap.size() == 1)
+ return true; // By definition
+ ArrayList<String> codeTypeList = new ArrayList<String>();
+ Iterator<String> itr = domainMap.keySet().iterator();
+ while (itr.hasNext())
+ {
+ String domainName = itr.next();
+ AmqpVersionSet versionSet = domainMap.get(domainName);
+ String codeType = generator.getGeneratedType(domainName, versionSet.first());
+ if (!codeTypeList.contains(codeType))
+ codeTypeList.add(codeType);
+ }
+ return codeTypeList.size() == 1;
+ }
+
+ public boolean isConsistent(Generator generator)
+ throws AmqpTypeMappingException
+ {
+ if (!isCodeTypeConsistent(generator))
+ return false;
+ if (ordinalMap.size() != 1)
+ return false;
+ // Since the various doamin names map to the same code type, add the version occurrences
+ // across all domains to see we have all possible versions covered
+ int vCntr = 0;
+ Iterator<String> itr = domainMap.keySet().iterator();
+ while (itr.hasNext())
+ vCntr += domainMap.get(itr.next()).size();
+ return vCntr == generator.globalVersionSet.size();
+ }
+
+ public void print(PrintStream out, int marginSize, int tabSize)
+ {
+ String margin = Utils.createSpaces(marginSize);
+ out.println(margin + "[F] " + name + ": " + versionSet);
+
+ Iterator<Integer> iItr = ordinalMap.keySet().iterator();
+ while (iItr.hasNext())
+ {
+ Integer ordinalValue = iItr.next();
+ AmqpVersionSet versionList = ordinalMap.get(ordinalValue);
+ out.println(margin + " [O] " + ordinalValue + " : " + versionList.toString());
+ }
+
+ Iterator<String> sItr = domainMap.keySet().iterator();
+ while (sItr.hasNext())
+ {
+ String domainKey = sItr.next();
+ AmqpVersionSet versionList = domainMap.get(domainKey);
+ out.println(margin + " [D] " + domainKey + " : " + versionList.toString());
+ }
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpFieldMap.java b/gentools/org/apache/qpid/gentools/AmqpFieldMap.java
new file mode 100644
index 0000000000..8e7421b45a
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpFieldMap.java
@@ -0,0 +1,271 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.TreeMap;
+
+@SuppressWarnings("serial")
+public class AmqpFieldMap extends TreeMap<String, AmqpField>
+{
+ public AmqpFieldMap getFieldMapForOrdinal(int ordinal)
+ {
+ AmqpFieldMap newMap = new AmqpFieldMap();
+ Iterator<String> i = keySet().iterator();
+ while (i.hasNext())
+ {
+ String fieldName = i.next();
+ AmqpField field = get(fieldName);
+ TreeMap<Integer, AmqpVersionSet> ordinalMap = field.ordinalMap;
+ AmqpVersionSet ordinalVersions = ordinalMap.get(ordinal);
+ if (ordinalVersions != null)
+ newMap.put(fieldName, field);
+ }
+ return newMap;
+ }
+
+ public boolean isDomainConsistent(Generator generator, AmqpVersionSet versionSet)
+ throws AmqpTypeMappingException
+ {
+ if (size() != 1) // Only one field for this ordinal
+ return false;
+ return get(firstKey()).isConsistent(generator);
+ }
+
+ public int getNumFields(AmqpVersion version)
+ {
+ int fCntr = 0;
+ Iterator<String> fItr = keySet().iterator();
+ while (fItr.hasNext())
+ {
+ AmqpField field = get(fItr.next());
+ if (field.versionSet.contains(version))
+ fCntr++;
+ }
+ return fCntr;
+ }
+
+ public String parseFieldMap(Method commonGenerateMethod, Method mangledGenerateMethod,
+ int indentSize, int tabSize, Generator codeGenerator)
+ throws AmqpTypeMappingException, IllegalAccessException, InvocationTargetException
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String cr = Utils.lineSeparator;
+ StringBuffer sb = new StringBuffer();
+
+ if (commonGenerateMethod == null)
+ {
+ // Generate warnings in code if required methods are null.
+ sb.append(indent + "/*********************************************************" + cr);
+ sb.append(indent + " * WARNING: Generated code could be missing." + cr);
+ sb.append(indent + " * In call to parseFieldMap(), generation method was null." + cr);
+ sb.append(indent + " * Check for NoSuchMethodException on startup." + cr);
+ sb.append(indent + " *********************************************************/" + cr);
+ }
+
+ Iterator<String> itr = keySet().iterator();
+ while (itr.hasNext())
+ {
+ String fieldName = itr.next();
+ AmqpField field = get(fieldName);
+ if (field.isCodeTypeConsistent(codeGenerator))
+ {
+ // All versions identical - Common declaration
+ String domainName = field.domainMap.firstKey();
+ AmqpVersionSet versionSet = field.domainMap.get(domainName);
+ String codeType = codeGenerator.getGeneratedType(domainName, versionSet.first());
+ if (commonGenerateMethod != null)
+ sb.append(commonGenerateMethod.invoke(codeGenerator, codeType, field, versionSet,
+ indentSize, tabSize, itr.hasNext()));
+ }
+ else if (mangledGenerateMethod != null) // Version-mangled
+ {
+ sb.append(mangledGenerateMethod.invoke(codeGenerator, field, indentSize, tabSize,
+ itr.hasNext()));
+ }
+ }
+ return sb.toString();
+ }
+
+ public String parseFieldMapOrdinally(Method generateMethod, Method bitGenerateMethod,
+ int indentSize, int tabSize, Generator codeGenerator)
+// int indentSize, int tabSize, AmqpVersionSet versionSet, AmqpDomainMap globalDomainMap)
+ throws AmqpTypeMappingException, IllegalAccessException, InvocationTargetException
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String cr = Utils.lineSeparator;
+ StringBuffer sb = new StringBuffer();
+
+ // Generate warnings in code if required methods are null.
+ if (generateMethod == null || bitGenerateMethod == null)
+ {
+ sb.append(indent + "/***********************************************" + cr);
+ sb.append(indent + " * WARNING: In call to parseFieldMapOrdinally():" + cr);
+ if (generateMethod == null)
+ sb.append(indent + " * => generateMethod is null." + cr);
+ if (bitGenerateMethod == null)
+ sb.append(indent + " * => bitGenerateMethod is null." + cr);
+ sb.append(indent + " * Generated code could be missing." + cr);
+ sb.append(indent + " * Check for NoSuchMethodException on startup." + cr);
+ sb.append(indent + " ***********************************************/" + cr);
+ }
+
+ /* We must process elements in ordinal order because adjacent booleans (bits)
+ * must be combined into a single byte (in groups of up to 8). Start with shared
+ * declarations until an ordinal divergence is found. (For most methods where
+ * there is no difference between versions, this will simplify the generated
+ * code. */
+
+ ArrayList<String> bitFieldList = new ArrayList<String>();
+ boolean ordinalDivergenceFlag = false;
+ int ordinal = 0;
+ while (ordinal < size() && !ordinalDivergenceFlag)
+ {
+ /* Since the getFieldMapOrdinal() function may map more than one Field to
+ * an ordinal, the number of ordinals may be less than the total number of
+ * fields in the fieldMap. Check for empty fieldmaps... */
+ AmqpFieldMap ordinalFieldMap = getFieldMapForOrdinal(ordinal);
+ if (ordinalFieldMap.size() > 0)
+ {
+ if (ordinalFieldMap.isDomainConsistent(codeGenerator, codeGenerator.globalVersionSet))
+ {
+ String fieldName = ordinalFieldMap.firstKey();
+ String domain = ordinalFieldMap.get(fieldName).domainMap.firstKey();
+ String domainType = codeGenerator.getDomainType(domain,
+ codeGenerator.globalVersionSet.first());
+ if (domainType.compareTo("bit") == 0)
+ bitFieldList.add(fieldName);
+ else if (bitFieldList.size() > 0)
+ {
+ // End of bit types - handle deferred bit type generation
+ if (bitGenerateMethod != null)
+ sb.append(bitGenerateMethod.invoke(codeGenerator, bitFieldList, ordinal,
+ indentSize, tabSize));
+ bitFieldList.clear();
+ }
+ if (!ordinalDivergenceFlag)
+ {
+ // Defer generation of bit types until all adjacent bits have been
+ // accounted for.
+ if (bitFieldList.size() == 0 && generateMethod != null)
+ sb.append(generateMethod.invoke(codeGenerator, domainType, fieldName, ordinal,
+ indentSize, tabSize));
+ }
+ ordinal++;
+ }
+ else
+ {
+ ordinalDivergenceFlag = true;
+ }
+ }
+ }
+
+ // Check if there is still more to do under a version-specific breakout
+ if (ordinalDivergenceFlag && ordinal< size())
+ {
+ // 1. Cycle through all versions in order, create outer if(version) structure
+ AmqpVersion[] versionArray = new AmqpVersion[codeGenerator.globalVersionSet.size()];
+ codeGenerator.globalVersionSet.toArray(versionArray);
+ for (int v=0; v<versionArray.length; v++)
+ {
+ sb.append(indent);
+ if (v > 0)
+ sb.append("else ");
+ sb.append("if (major == " + versionArray[v].getMajor() + " && minor == " +
+ versionArray[v].getMinor() + ")" + cr);
+ sb.append(indent + "{" + cr);
+
+ // 2. Cycle though each ordinal from where we left off in the loop above.
+ ArrayList<String> bitFieldList2 = new ArrayList<String>(bitFieldList);
+ for (int o = ordinal; o<size(); o++)
+ {
+ AmqpFieldMap ordinalFieldMap = getFieldMapForOrdinal(o);
+ if (ordinalFieldMap.size() > 0)
+ {
+ // 3. Cycle through each of the fields that have this ordinal.
+ Iterator<String> i = ordinalFieldMap.keySet().iterator();
+ while (i.hasNext())
+ {
+ String fieldName = i.next();
+ AmqpField field = ordinalFieldMap.get(fieldName);
+
+ // 4. Some fields may have more than one ordinal - match by both
+ // ordinal and version.
+ Iterator<Integer> j = field.ordinalMap.keySet().iterator();
+ while (j.hasNext())
+ {
+ int thisOrdinal = j.next();
+ AmqpVersionSet v1 = field.ordinalMap.get(thisOrdinal);
+ if (thisOrdinal == o && v1.contains(versionArray[v]))
+ {
+ // 5. Now get the domain for this version
+ int domainCntr = 0;
+ Iterator<String> k = field.domainMap.keySet().iterator();
+ while (k.hasNext())
+ {
+ // Mangle domain-divergent field names
+ String mangledFieldName = fieldName;
+ if (field.domainMap.size() > 1)
+ mangledFieldName += "_" + (domainCntr++);
+ String domainName = k.next();
+ AmqpVersionSet v2 = field.domainMap.get(domainName);
+ if (v2.contains(versionArray[v]))
+ {
+ // 6. (Finally!!) write the declaration
+ String domainType = codeGenerator.getDomainType(domainName,
+ versionArray[v]);
+ if (domainType.compareTo("bit") == 0)
+ bitFieldList2.add(mangledFieldName);
+ else if (bitFieldList2.size() > 0)
+ {
+ // End of bit types - handle deferred bit type generation
+ if (bitGenerateMethod != null)
+ sb.append(bitGenerateMethod.invoke(codeGenerator,
+ bitFieldList2, o, indentSize + tabSize,
+ tabSize));
+ bitFieldList2.clear();
+ }
+ // Defer generation of bit types until all adjacent bits have
+ // been accounted for.
+ if (bitFieldList2.size() == 0 && generateMethod != null)
+ sb.append(generateMethod.invoke(codeGenerator, domainType,
+ mangledFieldName, o, indentSize + tabSize, tabSize));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ // Check for remaining deferred bits
+ if (bitFieldList2.size() > 0 && bitGenerateMethod != null)
+ sb.append(bitGenerateMethod.invoke(codeGenerator, bitFieldList2, size(),
+ indentSize + tabSize, tabSize));
+ sb.append(indent + "}" + cr);
+ }
+ }
+ // Check for remaining deferred bits
+ else if (bitFieldList.size() > 0 && bitGenerateMethod != null)
+ sb.append(bitGenerateMethod.invoke(codeGenerator, bitFieldList, size(),
+ indentSize, tabSize));
+ return sb.toString();
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpMethod.java b/gentools/org/apache/qpid/gentools/AmqpMethod.java
new file mode 100644
index 0000000000..37c254e32c
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpMethod.java
@@ -0,0 +1,97 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.io.PrintStream;
+import java.util.Iterator;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class AmqpMethod implements Printable, NodeAware
+{
+ public LanguageConverter converter;
+ public AmqpVersionSet versionSet;
+ public AmqpFieldMap fieldMap;
+ public String name;
+ public AmqpOrdinalMap indexMap;
+
+ public AmqpMethod(String name, LanguageConverter converter)
+ {
+ this.name = name;
+ this.converter = converter;
+ versionSet = new AmqpVersionSet();
+ fieldMap = new AmqpFieldMap();
+ indexMap = new AmqpOrdinalMap();
+ }
+
+ public void addFromNode(Node methodNode, int ordinal, AmqpVersion version)
+ throws AmqpParseException, AmqpTypeMappingException
+ {
+ versionSet.add(version);
+ int index = Utils.getNamedIntegerAttribute(methodNode, "index");
+ AmqpVersionSet versionSet = indexMap.get(index);
+ if (versionSet != null)
+ versionSet.add(version);
+ else
+ {
+ versionSet = new AmqpVersionSet();
+ versionSet.add(version);
+ indexMap.put(index, versionSet);
+ }
+ NodeList nList = methodNode.getChildNodes();
+ int fieldCntr = 0;
+ for (int i=0; i<nList.getLength(); i++)
+ {
+ Node child = nList.item(i);
+ if (child.getNodeName().compareTo(Utils.ELEMENT_FIELD) == 0)
+ {
+ String fieldName = converter.prepareDomainName(Utils.getNamedAttribute(child, Utils.ATTRIBUTE_NAME));
+ AmqpField thisField = fieldMap.get(fieldName);
+ if (thisField == null)
+ {
+ thisField = new AmqpField(fieldName, converter);
+ fieldMap.put(fieldName, thisField);
+ }
+ thisField.addFromNode(child, fieldCntr++, version);
+ }
+ }
+ }
+
+ public void print(PrintStream out, int marginSize, int tabSize)
+ {
+ String margin = Utils.createSpaces(marginSize);
+ String tab = Utils.createSpaces(tabSize);
+ out.println(margin + "[M] " + name + ": " + versionSet);
+
+ Iterator<Integer> iItr = indexMap.keySet().iterator();
+ while (iItr.hasNext())
+ {
+ int index = iItr.next();
+ AmqpVersionSet indexVersionSet = indexMap.get(index);
+ out.println(margin + tab + "[I] " + index + indexVersionSet);
+ }
+
+ Iterator<String> sItr = fieldMap.keySet().iterator();
+ while (sItr.hasNext())
+ {
+ AmqpField thisField = fieldMap.get(sItr.next());
+ thisField.print(out, marginSize + tabSize, tabSize);
+ }
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpMethodMap.java b/gentools/org/apache/qpid/gentools/AmqpMethodMap.java
new file mode 100644
index 0000000000..07e236d2cd
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpMethodMap.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.util.TreeMap;
+
+@SuppressWarnings("serial")
+public class AmqpMethodMap extends TreeMap<String, AmqpMethod>
+{
+
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpModel.java b/gentools/org/apache/qpid/gentools/AmqpModel.java
new file mode 100644
index 0000000000..f379674f49
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpModel.java
@@ -0,0 +1,74 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.io.PrintStream;
+import java.util.Iterator;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class AmqpModel implements Printable, NodeAware
+{
+ public LanguageConverter converter;
+ public AmqpClassMap classMap;
+
+ public AmqpModel(LanguageConverter converter)
+ {
+ this.converter = converter;
+ this.converter.setModel(this);
+ classMap = new AmqpClassMap();
+ }
+
+ public void addFromNode(Node n, int o, AmqpVersion v)
+ throws AmqpParseException, AmqpTypeMappingException
+ {
+ NodeList nList = n.getChildNodes();
+ int eCntr = 0;
+ for (int i=0; i<nList.getLength(); i++)
+ {
+ Node c = nList.item(i);
+ if (c.getNodeName().compareTo(Utils.ELEMENT_CLASS) == 0)
+ {
+ String className = converter.prepareClassName(Utils.getNamedAttribute(c, Utils.ATTRIBUTE_NAME));
+ AmqpClass thisClass = classMap.get(className);
+ if (thisClass == null)
+ {
+ thisClass = new AmqpClass(className, converter);
+ classMap.put(className, thisClass);
+ }
+ thisClass.addFromNode(c, eCntr++, v);
+ }
+ }
+ }
+
+ public void print(PrintStream out, int marginSize, int tabSize)
+ {
+ out.println(Utils.createSpaces(marginSize) +
+ "[C]=class; [M]=method; [F]=field; [D]=domain; [I]=index; [O]=ordinal" + Utils.lineSeparator);
+ out.println(Utils.createSpaces(marginSize) + "Model:");
+
+ Iterator<String> i = classMap.keySet().iterator();
+ while (i.hasNext())
+ {
+ String className = i.next();
+ AmqpClass thisClass = classMap.get(className);
+ thisClass.print(out, marginSize + tabSize, tabSize);
+ }
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpOrdinalMap.java b/gentools/org/apache/qpid/gentools/AmqpOrdinalMap.java
new file mode 100644
index 0000000000..a340376d0e
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpOrdinalMap.java
@@ -0,0 +1,9 @@
+package org.apache.qpid.gentools;
+
+import java.util.TreeMap;
+
+@SuppressWarnings("serial")
+public class AmqpOrdinalMap extends TreeMap<Integer, AmqpVersionSet>
+{
+
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpParseException.java b/gentools/org/apache/qpid/gentools/AmqpParseException.java
new file mode 100644
index 0000000000..2a85001f99
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpParseException.java
@@ -0,0 +1,27 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+@SuppressWarnings("serial")
+public class AmqpParseException extends Exception
+{
+ public AmqpParseException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpTemplateException.java b/gentools/org/apache/qpid/gentools/AmqpTemplateException.java
new file mode 100644
index 0000000000..c0a3edb207
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpTemplateException.java
@@ -0,0 +1,10 @@
+package org.apache.qpid.gentools;
+
+@SuppressWarnings("serial")
+public class AmqpTemplateException extends Exception
+{
+ public AmqpTemplateException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpTypeMappingException.java b/gentools/org/apache/qpid/gentools/AmqpTypeMappingException.java
new file mode 100644
index 0000000000..b2304344c6
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpTypeMappingException.java
@@ -0,0 +1,27 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+@SuppressWarnings("serial")
+public class AmqpTypeMappingException extends Exception
+{
+ public AmqpTypeMappingException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpVersion.java b/gentools/org/apache/qpid/gentools/AmqpVersion.java
new file mode 100644
index 0000000000..f3f4f5833b
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpVersion.java
@@ -0,0 +1,54 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+public class AmqpVersion implements Comparable<AmqpVersion>
+{
+ private int major;
+ private int minor;
+
+ public AmqpVersion(int major, int minor)
+ {
+ this.major = major;
+ this.minor = minor;
+ }
+
+ public int getMajor()
+ {
+ return major;
+ }
+
+ public int getMinor()
+ {
+ return minor;
+ }
+
+ public int compareTo(AmqpVersion v)
+ {
+ if (major != v.major)
+ return major - v.major;
+ if (minor != v.minor)
+ return minor - v.minor;
+ return 0;
+ }
+
+ public String toString()
+ {
+ return major + "-" + minor;
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/AmqpVersionSet.java b/gentools/org/apache/qpid/gentools/AmqpVersionSet.java
new file mode 100644
index 0000000000..608a319146
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/AmqpVersionSet.java
@@ -0,0 +1,31 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.io.PrintStream;
+//import java.util.ArrayList;
+import java.util.TreeSet;
+
+@SuppressWarnings("serial")
+public class AmqpVersionSet extends TreeSet<AmqpVersion> implements Printable
+{
+ public void print(PrintStream out, int marginSize, int tabSize)
+ {
+ out.print(Utils.createSpaces(marginSize) + "Version Set: " + toString());
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/CppGenerator.java b/gentools/org/apache/qpid/gentools/CppGenerator.java
new file mode 100644
index 0000000000..3405e48984
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/CppGenerator.java
@@ -0,0 +1,217 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.util.TreeMap;
+
+public class CppGenerator extends Generator
+{
+ private class DomainInfo
+ {
+ public String type;
+ public String size;
+ public DomainInfo(String domain, String size)
+ {
+ this.type = domain;
+ this.size = size;
+ }
+ }
+
+ private static TreeMap<String, DomainInfo> typeMap = new TreeMap<String, DomainInfo>();
+
+ public CppGenerator(AmqpVersionSet versionList)
+ {
+ super(versionList);
+ // Load C++ type and size maps.
+ // Adjust or add to these lists as new types are added/defined.
+ // The char '#' will be replaced by the field variable name.
+ typeMap.put("bit", new DomainInfo(
+ "bool", // domain
+ "1")); // size
+ typeMap.put("long", new DomainInfo(
+ "u_int32_t", // domain
+ "4")); // size
+ typeMap.put("longlong", new DomainInfo(
+ "u_int64_t", // domain
+ "8")); // size
+ typeMap.put("longstr", new DomainInfo(
+ "string", // domain
+ "4 + #.length()")); // size
+ typeMap.put("octet", new DomainInfo(
+ "u_int8_t", // domain
+ "1")); // size
+ typeMap.put("short", new DomainInfo(
+ "u_int16_t", // domain
+ "2")); // size
+ typeMap.put("shortstr", new DomainInfo(
+ "string", // domain
+ "1 + #.length()")); // size
+ typeMap.put("table", new DomainInfo(
+ "FieldTable", // domain
+ "#.size()")); // size
+ typeMap.put("timestamp", new DomainInfo(
+ "u_int64_t", // domain
+ "8")); // decode expression
+ }
+
+ // === Start of methods for Interface LanguageConverter ===
+
+ public String prepareClassName(String className)
+ {
+ return camelCaseName(className, true);
+ }
+
+ public String prepareMethodName(String methodName)
+ {
+ return camelCaseName(methodName, false);
+ }
+
+ public String prepareDomainName(String domainName)
+ {
+ return camelCaseName(domainName, false);
+ }
+
+ public String getDomainType(String domainType, AmqpVersion version)
+ throws AmqpTypeMappingException
+ {
+ String domain = globalDomainMap.getDomainType(domainType, version);
+ String type = typeMap.get(domain).type;
+ if (type == null)
+ throw new AmqpTypeMappingException("Domain type \"" + domainType + "\" not found in Java typemap.");
+ return type;
+ }
+
+ public String getGeneratedType(String domainName, AmqpVersion version)
+ throws AmqpTypeMappingException
+ {
+ String domainType = getDomainType(domainName, version);
+ return typeMap.get(domainType).type;
+ }
+
+ // === Abstract methods from class Generator - C++-specific implementation ===
+
+ @Override
+ protected String prepareFilename(String filenameTemplate, AmqpClass thisClass, AmqpMethod method,
+ AmqpField field)
+ {
+ StringBuffer sb = new StringBuffer(filenameTemplate);
+ if (thisClass != null)
+ replaceToken(sb, "${CLASS}", thisClass.name);
+ if (method != null)
+ replaceToken(sb, "${METHOD}", method.name);
+ if (field != null)
+ replaceToken(sb, "${FIELD}", field.name);
+ return sb.toString();
+ }
+
+ @Override
+ protected String processToken(String snipitKey, AmqpClass thisClass, AmqpMethod method, AmqpField field)
+ throws AmqpTemplateException
+ {
+ if (snipitKey.compareTo("${property_flags_initializer}") == 0)
+ {
+ StringBuffer sb = new StringBuffer();
+ // TODO
+ return sb.toString();
+ }
+ throw new AmqpTemplateException("Template token " + snipitKey + " unknown.");
+ }
+
+ @Override
+ protected void processClassList(StringBuffer sb, int tokStart, int tokEnd, AmqpModel model)
+ throws AmqpTemplateException
+ {
+// TODO
+ }
+
+ @Override
+ protected void processMethodList(StringBuffer sb, int tokStart, int tokEnd, AmqpClass thisClass)
+ throws AmqpTemplateException
+ {
+// TODO
+ }
+
+ @Override
+ protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex,
+ AmqpFieldMap fieldMap)
+ throws AmqpTypeMappingException, AmqpTemplateException
+ {
+// TODO
+ }
+
+// @Override
+// protected String generateFieldDeclaration(AmqpFieldMap fieldMap, int indentSize)
+// throws AmqpTypeMappingException
+// {
+// String indent = Utils.createSpaces(indentSize);
+// StringBuffer sb = new StringBuffer(indent + "// [FieldDeclaration]" + Utils.lineSeparator);
+// // TODO
+// return sb.toString();
+// }
+//
+// @Override
+// protected String generateFieldGetMethod(AmqpFieldMap fieldMap, int indentSize, int tabSize)
+// throws AmqpTypeMappingException
+// {
+// String indent = Utils.createSpaces(indentSize);
+//// String tab = Utils.createSpaces(tabSize);
+// StringBuffer sb = new StringBuffer(indent + "// [FieldGetMethod]" + Utils.lineSeparator);
+// // TODO
+// return sb.toString();
+// }
+//
+// @Override
+// protected String generateContentHeaderGetSetMethod(AmqpFieldMap fieldMap, int indentSize,
+// int tabSize)
+// throws AmqpTypeMappingException
+// {
+// String indent = Utils.createSpaces(indentSize);
+//// String tab = Utils.createSpaces(tabSize);
+// StringBuffer sb = new StringBuffer(indent + "// Property get/set methods" + Utils.lineSeparator);
+// // TODO
+// return sb.toString();
+// }
+//
+// @Override
+// protected String generateCodeSnippet(String token, AmqpFieldMap fieldMap, int indentSize,
+// int tabSize)
+// throws AmqpTypeMappingException
+// {
+// String indent = Utils.createSpaces(indentSize);
+//// String tab = Utils.createSpaces(tabSize);
+// StringBuffer sb = new StringBuffer(indent + "// [Code snippet " + token + "]" + Utils.lineSeparator);
+// // TODO
+// return sb.toString();
+// }
+
+ // Private helper functions unique to C++
+
+ private String camelCaseName(String name, boolean upperFirstFlag)
+ {
+ StringBuffer ccn = new StringBuffer();
+ String[] toks = name.split("[-_.\\ ]");
+ for (int i=0; i<toks.length; i++)
+ {
+ StringBuffer b = new StringBuffer(toks[i]);
+ if (upperFirstFlag || i>0)
+ b.setCharAt(0, Character.toUpperCase(toks[i].charAt(0)));
+ ccn.append(b);
+ }
+ return ccn.toString();
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/Generator.java b/gentools/org/apache/qpid/gentools/Generator.java
new file mode 100644
index 0000000000..db75599b45
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/Generator.java
@@ -0,0 +1,402 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Set;
+
+public abstract class Generator implements LanguageConverter
+{
+ // This string is reproduced in every generated file as a comment
+ // TODO: Tie the version info into the build system.
+ protected static final String generatorInfo = "Qpid Gentools v.0.1";
+
+ protected ArrayList<String[]> modelTemplateList;
+ protected ArrayList<String[]> classTemplateList;
+ protected ArrayList<String[]> methodTemplateList;
+ protected ArrayList<String[]> fieldTemplateList;
+ protected String genDir;
+
+ protected AmqpVersionSet globalVersionSet;
+ protected AmqpDomainMap globalDomainMap;
+ protected AmqpModel model;
+
+ protected int generatedFileCounter;
+
+ public Generator(AmqpVersionSet versionList)
+ {
+ this.globalVersionSet = versionList;
+ modelTemplateList = new ArrayList<String[]>();
+ classTemplateList = new ArrayList<String[]>();
+ methodTemplateList = new ArrayList<String[]>();
+ fieldTemplateList = new ArrayList<String[]>();
+ generatedFileCounter = 0;
+ }
+
+ public int getNumberGeneratedFiles()
+ {
+ return generatedFileCounter;
+ }
+
+ public void setDomainMap(AmqpDomainMap domainMap)
+ {
+ this.globalDomainMap = domainMap;
+ }
+
+ public AmqpDomainMap getDomainMap()
+ {
+ return globalDomainMap;
+ }
+
+ public void setModel(AmqpModel model)
+ {
+ this.model = model;
+ }
+
+ public AmqpModel getModel()
+ {
+ return model;
+ }
+
+ public void initializeTemplates(File[] modelTemplateFiles, File[] classTemplatesFiles,
+ File[] methodTemplatesFiles, File[] fieldTemplatesFiles)
+ throws FileNotFoundException, IOException
+ {
+ if (modelTemplateFiles.length > 0)
+ {
+ System.out.println("Model template file(s):");
+ for (int t=0; t<modelTemplateFiles.length; t++)
+ {
+ System.out.println(" " + modelTemplateFiles[t].getAbsolutePath());
+ String template[] = {modelTemplateFiles[t].getName(), loadTemplate(modelTemplateFiles[t])};
+ modelTemplateList.add(template);
+ }
+ }
+ if (classTemplatesFiles.length > 0)
+ {
+ System.out.println("Class template file(s):");
+ for (int c=0; c<classTemplatesFiles.length; c++)
+ {
+ System.out.println(" " + classTemplatesFiles[c].getAbsolutePath());
+ String template[] = {classTemplatesFiles[c].getName(), loadTemplate(classTemplatesFiles[c])};
+ classTemplateList.add(template);
+ }
+ }
+ if (methodTemplatesFiles.length > 0)
+ {
+ System.out.println("Method template file(s):");
+ for (int m=0; m<methodTemplatesFiles.length; m++)
+ {
+ System.out.println(" " + methodTemplatesFiles[m].getAbsolutePath());
+ String template[] = {methodTemplatesFiles[m].getName(), loadTemplate(methodTemplatesFiles[m])};
+ methodTemplateList.add(template);
+ }
+ }
+ if (fieldTemplatesFiles.length > 0)
+ {
+ System.out.println("Field template file(s):");
+ for (int f=0; f<fieldTemplatesFiles.length; f++)
+ {
+ System.out.println(" " + fieldTemplatesFiles[f].getAbsolutePath());
+ String template[] = {fieldTemplatesFiles[f].getName(), loadTemplate(fieldTemplatesFiles[f])};
+ fieldTemplateList.add(template);
+ }
+ }
+ }
+
+ public void generate(File genDir)
+ throws TargetDirectoryException, IOException, AmqpTypeMappingException,
+ AmqpTemplateException, IllegalAccessException, InvocationTargetException
+ {
+ prepareTargetDirectory(genDir, true);
+ System.out.println("Generation directory: " + genDir.getAbsolutePath());
+ this.genDir = genDir.getAbsolutePath();
+
+ // Use all model-level templates
+ for (int t = 0; t < classTemplateList.size(); t++)
+ {
+ processTemplate(modelTemplateList.get(t), null, null, null);
+ }
+
+ // Cycle through classes
+ Set<String> ckeys = model.classMap.keySet();
+ Iterator<String> citr = ckeys.iterator();
+ while (citr.hasNext())
+ {
+ String className = citr.next();
+ AmqpClass thisClass = model.classMap.get(className);
+
+ // Use all class-level templates
+ for (int c = 0; c < classTemplateList.size(); c++)
+ {
+ processTemplate(classTemplateList.get(c), thisClass, null, null);
+ }
+
+ // Cycle through all methods
+ Set<String> mkeys = thisClass.methodMap.keySet();
+ Iterator<String> mitr = mkeys.iterator();
+ while (mitr.hasNext())
+ {
+ String methodName = mitr.next();
+ AmqpMethod method = thisClass.methodMap.get(methodName);
+
+ // Use all method-level templates
+ for (int m = 0; m < methodTemplateList.size(); m++)
+ {
+ processTemplate(methodTemplateList.get(m), thisClass, method, null);
+ }
+
+ // Cycle through all fields
+ Set<String> fkeys = method.fieldMap.keySet();
+ Iterator<String> fitr = fkeys.iterator();
+ while (fitr.hasNext())
+ {
+ String fieldName = fitr.next();
+ AmqpField field = method.fieldMap.get(fieldName);
+
+ // Use all field-level templates
+ for (int f = 0; f < fieldTemplateList.size(); f++)
+ {
+ processTemplate(fieldTemplateList.get(f), thisClass, method, field);
+ }
+ }
+ }
+ }
+ }
+
+ abstract protected String prepareFilename(String filenameTemplate, AmqpClass thisClass, AmqpMethod method,
+ AmqpField field);
+
+ abstract protected String processToken(String token, AmqpClass thisClass, AmqpMethod method, AmqpField field)
+ throws AmqpTemplateException;
+
+ abstract protected void processClassList(StringBuffer sb, int tokStart, int tokEnd, AmqpModel model)
+ throws AmqpTemplateException;
+
+ abstract protected void processMethodList(StringBuffer sb, int tokStart, int tokEnd, AmqpClass thisClass)
+ throws AmqpTemplateException;
+
+ abstract protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex,
+ AmqpFieldMap fieldMap)
+ throws AmqpTypeMappingException, AmqpTemplateException, IllegalAccessException,
+ InvocationTargetException;
+
+ protected void processVersionList(StringBuffer sb, int tokStart, int tokEnd)
+ throws AmqpTypeMappingException
+ {
+ int lend = sb.indexOf(Utils.lineSeparator, tokStart) + 1; // Include cr at end of line
+ String tline = sb.substring(tokEnd, lend); // Line excluding line marker, including cr
+ sb.delete(tokStart, lend);
+ AmqpVersion[] versionArray = new AmqpVersion[globalVersionSet.size()];
+ globalVersionSet.toArray(versionArray);
+ for (int i=0; i<versionArray.length; i++)
+ {
+ // Insert copy of target line
+ StringBuffer isb = new StringBuffer(tline);
+ replaceToken(isb, "${major}", String.valueOf(versionArray[i].getMajor()));
+ replaceToken(isb, "${minor}", String.valueOf(versionArray[i].getMinor()));
+ sb.insert(tokStart, isb.toString());
+ tokStart += isb.length();
+ }
+ }
+
+ // TODO: This could be a little more elegant - overload this for the various combinations
+ // of call instead of passing nulls.
+ protected void processTemplate(String[] template, AmqpClass thisClass, AmqpMethod method, AmqpField field)
+ throws IOException, AmqpTemplateException, AmqpTypeMappingException, IllegalAccessException,
+ InvocationTargetException
+ {
+ StringBuffer sb = new StringBuffer(template[1]);
+ String filename = prepareFilename(getTemplateFileName(sb), thisClass, method, field);
+ try { processAllLists(sb, thisClass, method); }
+ catch (AmqpTemplateException e)
+ {
+ System.out.println("WARNING: " + template[0] + ": " + e.getMessage());
+ }
+ try { processAllTokens(sb, thisClass, method, field); }
+ catch (AmqpTemplateException e)
+ {
+ System.out.println("WARNING: " + template[0] + ": " + e.getMessage());
+ }
+ writeTargetFile(sb, new File(genDir + Utils.fileSeparator + filename));
+ generatedFileCounter ++;
+ }
+
+ // Helper functions common to all generators
+
+ protected static void prepareTargetDirectory(File dir, boolean createFlag)
+ throws TargetDirectoryException
+ {
+ if (dir.exists())
+ {
+ if (!dir.isDirectory())
+ throw new TargetDirectoryException("\"" + dir.getAbsolutePath() +
+ "\" exists, but is not a directory.");
+ }
+ else if (createFlag) // Create dir
+ {
+ if(!dir.mkdirs())
+ throw new TargetDirectoryException("Unable to create directory \"" +
+ dir.getAbsolutePath() + "\".");
+ }
+ else
+ throw new TargetDirectoryException("Directory \"" + dir.getAbsolutePath() +
+ "\" not found.");
+
+ }
+
+ protected void processAllLists(StringBuffer sb, AmqpClass thisClass, AmqpMethod method)
+ throws AmqpTemplateException, AmqpTypeMappingException, IllegalAccessException,
+ InvocationTargetException
+ {
+ int lstart = sb.indexOf("%{");
+ while (lstart != -1)
+ {
+ int lend = sb.indexOf("}", lstart + 2);
+ if (lend > 0)
+ {
+ String listToken = sb.substring(lstart + 2, lend);
+ if (listToken.compareTo("VLIST") == 0)
+ {
+ processVersionList(sb, lstart, lend + 1);
+ }
+ else if (listToken.compareTo("CLIST") == 0)
+ {
+ processClassList(sb, lstart, lend + 1, model);
+ }
+ else if (listToken.compareTo("MLIST") == 0)
+ {
+ processMethodList(sb, lstart, lend + 1, thisClass);
+ }
+ else if (listToken.compareTo("FLIST") == 0)
+ {
+ // Pass the FieldMap from either a class or a method.
+ // If this is called from a class-level template, we assume that the
+ // class field list is required. In this case, method will be null.
+ processFieldList(sb, lstart, lend + 1,
+ (method == null ? thisClass.fieldMap : method.fieldMap));
+ }
+ else
+ {
+ throw new AmqpTemplateException("Unknown list token \"%{" + listToken +
+ "}\" found in template at index " + lstart + ".");
+ }
+ }
+ lstart = sb.indexOf("%{", lstart + 1);
+ }
+ }
+
+ protected void processAllTokens(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, AmqpField field)
+ throws AmqpTemplateException
+ {
+ int lstart = sb.indexOf("${");
+ while (lstart != -1)
+ {
+ int lend = sb.indexOf("}", lstart + 2);
+ if (lend > 0)
+ {
+ String token = sb.substring(lstart, lend + 1);
+ replaceToken(sb, lstart, token, processToken(token, thisClass, method, field));
+ }
+ lstart = sb.indexOf("${", lstart);
+ }
+ }
+
+ protected static void writeTargetFile(StringBuffer sb, File f)
+ throws IOException
+ {
+ FileWriter fw = new FileWriter(f);
+ fw.write(sb.toString().toCharArray());
+ fw.flush();
+ fw.close();
+ }
+
+ protected static String getTemplateFileName(StringBuffer sb)
+ throws AmqpTemplateException
+ {
+ if (sb.charAt(0) != '&')
+ throw new AmqpTemplateException("No filename marker &{filename} found at start of template.");
+ int cr = sb.indexOf(Utils.lineSeparator);
+ if (cr < 0)
+ throw new AmqpTemplateException("Bad template structure - unable to find first line.");
+ String fileName = sb.substring(2, cr-1);
+ sb.delete(0, cr + 1);
+ return fileName;
+ }
+
+ protected static void replaceToken(StringBuffer sb, String token, String replacement)
+ {
+ replaceToken(sb, 0, token, replacement);
+ }
+
+ protected static void replaceToken(StringBuffer sb, int index, String token, String replacement)
+ {
+ if (replacement != null)
+ {
+ int start = sb.indexOf(token, index);
+ int len = token.length();
+ // Find first letter in token and determine if it is capitalized
+ char firstTokenLetter = getFirstLetter(token);
+ if (firstTokenLetter != 0 && Character.isUpperCase(firstTokenLetter))
+ sb.replace(start, start+len, Utils.firstUpper(replacement));
+ else
+ sb.replace(start, start+len, replacement);
+ }
+ }
+
+ private static char getFirstLetter(String str)
+ {
+ int len = str.length();
+ int index = 0;
+ char tokChar = str.charAt(index);
+ while (!Character.isLetter(tokChar) && index<len-1)
+ tokChar = str.charAt(++index);
+ if (Character.isLetter(tokChar))
+ return tokChar;
+ return 0;
+ }
+
+ private static String loadTemplate(File f)
+ throws FileNotFoundException, IOException
+ {
+ StringBuffer sb = new StringBuffer();
+ FileReader fr = new FileReader(f);
+ LineNumberReader lnr = new LineNumberReader(fr);
+ String line = lnr.readLine();
+ while (line != null)
+ {
+ // Strip lines starting with '#' in template - treat these lines as template comments
+ if (line.length() > 0 && line.charAt(0) != '#')
+ sb.append(line + Utils.lineSeparator);
+ else
+ sb.append(Utils.lineSeparator);
+ line = lnr.readLine();
+ }
+ lnr.close();
+ fr.close();
+ return sb.toString();
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/JavaGenerator.java b/gentools/org/apache/qpid/gentools/JavaGenerator.java
new file mode 100644
index 0000000000..dc19d0e14a
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/JavaGenerator.java
@@ -0,0 +1,1451 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.TreeMap;
+
+public class JavaGenerator extends Generator
+{
+ static String cr = Utils.lineSeparator;
+
+ private class DomainInfo
+ {
+ public String type;
+ public String size;
+ public String encodeExpression;
+ public String decodeExpression;
+ public DomainInfo(String domain, String size, String encodeExpression, String decodeExpression)
+ {
+ this.type = domain;
+ this.size = size;
+ this.encodeExpression = encodeExpression;
+ this.decodeExpression = decodeExpression;
+ }
+ }
+
+ private static TreeMap<String, DomainInfo> typeMap = new TreeMap<String, DomainInfo>();
+
+ // Methods used for generation of code snippets called from the field map parsers
+
+ // Common methods
+ static private Method declarationGenerateMethod;
+ static private Method mangledDeclarationGenerateMethod;
+
+ // Methods for MessageBody classes
+ static private Method mbGetGenerateMethod;
+ static private Method mbMangledGetGenerateMethod;
+ static private Method mbParamListGenerateMethod;
+ static private Method mbMangledParamListGenerateMethod;
+ static private Method mbBodyInitGenerateMethod;
+ static private Method mbMangledBodyInitGenerateMethod;
+ static private Method mbSizeGenerateMethod;
+ static private Method mbBitSizeGenerateMethod;
+ static private Method mbEncodeGenerateMethod;
+ static private Method mbBitEncodeGenerateMethod;
+ static private Method mbDecodeGenerateMethod;
+ static private Method mbBitDecodeGenerateMethod;
+ static private Method mbToStringGenerateMethod;
+ static private Method mbBitToStringGenerateMethod;
+
+ // Methods for PropertyContentHeader classes
+ static private Method pchClearGenerateMethod;
+ static private Method pchMangledClearGenerateMethod;
+ static private Method pchGetGenerateMethod;
+ static private Method pchMangledGetGenerateMethod;
+ static private Method pchSetGenerateMethod;
+ static private Method pchMangledSetGenerateMethod;
+ static private Method pchSizeGenerateMethod;
+ static private Method pchBitSizeGenerateMethod;
+ static private Method pchEncodeGenerateMethod;
+ static private Method pchBitEncodeGenerateMethod;
+ static private Method pchDecodeGenerateMethod;
+ static private Method pchBitDecodeGenerateMethod;
+ static private Method pchGetPropertyFlagsGenerateMethod;
+ static private Method pchBitGetPropertyFlagsGenerateMethod;
+ static private Method pchSetPropertyFlagsGenerateMethod;
+ static private Method pchBitSetPropertyFlagsGenerateMethod;
+
+ static
+ {
+ // **************
+ // Common methods
+ // **************
+
+ // Methods for AmqpFieldMap.parseFieldMap()
+
+ try { declarationGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateFieldDeclaration", String.class, AmqpField.class,
+ AmqpVersionSet.class, int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { mangledDeclarationGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMangledFieldDeclaration", AmqpField.class,
+ int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+
+ // *******************************
+ // Methods for MessageBody classes
+ // *******************************
+
+ // Methods for AmqpFieldMap.parseFieldMap()
+
+ try { mbGetGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbGetMethod", String.class, AmqpField.class,
+ AmqpVersionSet.class, int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { mbMangledGetGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbMangledGetMethod", AmqpField.class,
+ int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { mbParamListGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbParamList", String.class, AmqpField.class,
+ AmqpVersionSet.class, int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { mbMangledParamListGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbMangledParamList", AmqpField.class,
+ int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { mbBodyInitGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbBodyInit", String.class, AmqpField.class,
+ AmqpVersionSet.class, int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { mbMangledBodyInitGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbMangledBodyInit", AmqpField.class,
+ int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ // Methods for AmqpFieldMap.parseFieldMapOrdinally()
+
+ try { mbSizeGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbFieldSize", String.class, String.class,
+ int.class, int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { mbBitSizeGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbBitArrayFieldSize", ArrayList.class, int.class,
+ int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { mbEncodeGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbFieldEncode", String.class, String.class,
+ int.class, int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { mbBitEncodeGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbBitFieldEncode", ArrayList.class, int.class,
+ int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { mbDecodeGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbFieldDecode", String.class, String.class,
+ int.class, int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { mbBitDecodeGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbBitFieldDecode", ArrayList.class, int.class,
+ int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { mbToStringGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbFieldToString", String.class, String.class,
+ int.class, int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { mbBitToStringGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generateMbBitFieldToString", ArrayList.class, int.class,
+ int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ // *****************************************
+ // Methods for PropertyContentHeader classes
+ // *****************************************
+
+ // Methods for AmqpFieldMap.parseFieldMap()
+
+ try { pchClearGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchClearMethod", String.class, AmqpField.class,
+ AmqpVersionSet.class, int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchMangledClearGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchMangledClearMethod", AmqpField.class,
+ int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchSetGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchSetMethod", String.class, AmqpField.class,
+ AmqpVersionSet.class, int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchMangledSetGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchMangledSetMethod", AmqpField.class,
+ int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchGetGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchGetMethod", String.class, AmqpField.class,
+ AmqpVersionSet.class, int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchMangledGetGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchMangledGetMethod", AmqpField.class,
+ int.class, int.class, boolean.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ // Methods for AmqpFieldMap.parseFieldMapOrdinally()
+
+ try { pchSizeGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchFieldSize", String.class, String.class,
+ int.class, int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchBitSizeGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchBitArrayFieldSize", ArrayList.class, int.class,
+ int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchEncodeGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchFieldEncode", String.class, String.class,
+ int.class, int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchBitEncodeGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchBitFieldEncode", ArrayList.class, int.class,
+ int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchDecodeGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchFieldDecode", String.class, String.class,
+ int.class, int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchBitDecodeGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchBitFieldDecode", ArrayList.class, int.class,
+ int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchGetPropertyFlagsGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchGetPropertyFlags", String.class, String.class,
+ int.class, int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchBitGetPropertyFlagsGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchBitGetPropertyFlags", ArrayList.class, int.class,
+ int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchSetPropertyFlagsGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchSetPropertyFlags", String.class, String.class,
+ int.class, int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+
+ try { pchBitSetPropertyFlagsGenerateMethod = JavaGenerator.class.getDeclaredMethod(
+ "generatePchBitSetPropertyFlags", ArrayList.class, int.class,
+ int.class, int.class); }
+ catch (NoSuchMethodException e) { e.printStackTrace(); }
+ }
+
+ public JavaGenerator(AmqpVersionSet versionList)
+ {
+ super(versionList);
+ // Load Java type and size maps.
+ // Adjust or add to these lists as new types are added/defined.
+ // The char '#' will be replaced by the field variable name (any type).
+ // The char '~' will be replaced by the compacted bit array size (type bit only).
+ typeMap.put("bit", new DomainInfo(
+ "boolean", // Java code type
+ "~", // size
+ "EncodingUtils.writeBooleans(buffer, #)", // encode expression
+ "# = EncodingUtils.readBooleans(buffer)")); // decode expression
+ typeMap.put("long", new DomainInfo(
+ "long", // Java code type
+ "4", // size
+ "EncodingUtils.writeUnsignedInteger(buffer, #)", // encode expression
+ "# = buffer.getUnsignedInt()")); // decode expression
+ typeMap.put("longlong", new DomainInfo(
+ "long", // Java code type
+ "8", // size
+ "buffer.putLong(#)", // encode expression
+ "# = buffer.getLong()")); // decode expression
+ typeMap.put("longstr", new DomainInfo(
+ "String", // Java code type
+ "EncodingUtils.encodedLongStringLength(#)", // size
+ "EncodingUtils.writeLongStringBytes(buffer, #)", // encode expression
+ "# = EncodingUtils.readLongString(buffer)")); // decode expression
+ typeMap.put("octet", new DomainInfo(
+ "char", // Java code type
+ "1", // size
+ "buffer.putChar(#)", // encode expression
+ "# = buffer.getChar()")); // decode expression
+ typeMap.put("short", new DomainInfo(
+ "int", // Java code type
+ "2", // size
+ "EncodingUtils.writeUnsignedShort(buffer, #)", // encode expression
+ "# = buffer.getUnsignedShort()")); // decode expression
+ typeMap.put("shortstr", new DomainInfo(
+ "String", // Java code type
+ "EncodingUtils.encodedShortStringLength(#)", // size
+ "EncodingUtils.writeShortStringBytes(buffer, #)", // encode expression
+ "# = EncodingUtils.readShortString(buffer)")); // decode expression
+ typeMap.put("table", new DomainInfo(
+ "FieldTable", // Java code type
+ "EncodingUtils.encodedFieldTableLength(#)", // size
+ "EncodingUtils.writeFieldTableBytes(buffer, #)", // encode expression
+ "# = EncodingUtils.readFieldTable(buffer)")); // decode expression
+ typeMap.put("timestamp", new DomainInfo(
+ "long", // Java code type
+ "8", // size
+ "EncodingUtils.writeTimestamp(buffer, #)", // encode expression
+ "# = EncodingUtils.readTimestamp(buffer)")); // decode expression
+ }
+
+ // === Start of methods for Interface LanguageConverter ===
+
+ public String prepareClassName(String className)
+ {
+ return camelCaseName(className, true);
+ }
+
+ public String prepareMethodName(String methodName)
+ {
+ return camelCaseName(methodName, false);
+ }
+
+ public String prepareDomainName(String domainName)
+ {
+ return camelCaseName(domainName, false);
+ }
+
+ public String getDomainType(String domainName, AmqpVersion version)
+ throws AmqpTypeMappingException
+ {
+ return globalDomainMap.getDomainType(domainName, version);
+ }
+
+ public String getGeneratedType(String domainName, AmqpVersion version)
+ throws AmqpTypeMappingException
+ {
+ String domainType = globalDomainMap.getDomainType(domainName, version);
+ if (domainType == null)
+ throw new AmqpTypeMappingException("Domain type \"" + domainName + "\" not found in Java typemap.");
+ return typeMap.get(domainType).type;
+ }
+
+
+ // === Abstract methods from class Generator - Java-specific implementations ===
+
+ @Override
+ protected String prepareFilename(String filenameTemplate, AmqpClass thisClass, AmqpMethod method,
+ AmqpField field)
+ {
+ StringBuffer sb = new StringBuffer(filenameTemplate);
+ if (thisClass != null)
+ replaceToken(sb, "${CLASS}", thisClass.name);
+ if (method != null)
+ replaceToken(sb, "${METHOD}", method.name);
+ if (field != null)
+ replaceToken(sb, "${FIELD}", field.name);
+ return sb.toString();
+ }
+
+ @Override
+ protected String processToken(String token, AmqpClass thisClass, AmqpMethod method, AmqpField field)
+ throws AmqpTemplateException
+ {
+ if (token.compareTo("${GENERATOR}") == 0)
+ return generatorInfo;
+ if (token.compareTo("${CLASS}") == 0 && thisClass != null)
+ return thisClass.name;
+ if (token.compareTo("${CLASS_ID_INIT}") == 0 && thisClass != null)
+ return generateIndexInitializer("classIdMap", thisClass.indexMap, 8);
+ if (token.compareTo("${METHOD}") == 0 && method != null)
+ return method.name;
+ if (token.compareTo("${METHOD_ID_INIT}") == 0 && method != null)
+ return generateIndexInitializer("methodIdMap", method.indexMap, 8);
+ if (token.compareTo("${FIELD}") == 0 && field != null)
+ return field.name;
+
+ // This token is used only with class or method-level templates
+ if (token.compareTo("${pch_property_flags_declare}") == 0)
+ {
+ return generatePchPropertyFlagsDeclare();
+ }
+ else if (token.compareTo("${pch_property_flags_initializer}") == 0)
+ {
+ int mapSize = method == null ? thisClass.fieldMap.size() : method.fieldMap.size();
+ return generatePchPropertyFlagsInitializer(mapSize);
+ }
+ else if (token.compareTo("${pch_compact_property_flags_initializer}") == 0)
+ {
+ return generatePchCompactPropertyFlagsInitializer(thisClass, 8, 4);
+ }
+ else if (token.compareTo("${pch_compact_property_flags_check}") == 0)
+ {
+ return generatePchCompactPropertyFlagsCheck(thisClass, 8, 4);
+ }
+
+ // Oops!
+ throw new AmqpTemplateException("Template token " + token + " unknown.");
+ }
+
+ @Override
+ protected void processClassList(StringBuffer sb, int tokStart, int tokEnd, AmqpModel model)
+ throws AmqpTemplateException
+ {
+ 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);
+
+ if (token.compareTo("${reg_map_put_method}") == 0)
+ {
+ codeSnippet = generateRegistry(model, 8, 4);
+ }
+
+ else // Oops!
+ {
+ throw new AmqpTemplateException("Template token " + token + " unknown.");
+ }
+
+ sb.insert(tokStart, codeSnippet);
+ }
+
+ @Override
+ protected void processMethodList(StringBuffer sb, int tokStart, int tokEnd, AmqpClass thisClass)
+ throws AmqpTemplateException
+ {
+ 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);
+
+ //TODO - we don't have any cases of this (yet).
+ if (token.compareTo("${???}") == 0)
+ {
+ codeSnippet = token;
+ }
+ else // Oops!
+ {
+ throw new AmqpTemplateException("Template token " + token + " unknown.");
+ }
+
+ sb.insert(tokStart, codeSnippet);
+ }
+
+ @Override
+ protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex,
+ AmqpFieldMap fieldMap)
+ throws AmqpTypeMappingException, AmqpTemplateException, IllegalAccessException,
+ InvocationTargetException
+ {
+ 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);
+
+ // Field declarations - common to MethodBody and PropertyContentHeader classes
+ if (token.compareTo("${field_declaration}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMap(declarationGenerateMethod,
+ mangledDeclarationGenerateMethod, 4, 4, this);
+ }
+
+ // MethodBody classes
+ else if (token.compareTo("${mb_field_get_method}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMap(mbGetGenerateMethod,
+ mbMangledGetGenerateMethod, 4, 4, this);
+ }
+ else if (token.compareTo("${mb_field_parameter_list}") == 0)
+ {
+ // This is klunky... (cringe) TODO: Find a more elegant solution here sometime...
+ codeSnippet = fieldMap.size() > 0 ? Utils.createSpaces(42) + "," + cr : "";
+ codeSnippet += fieldMap.parseFieldMap(mbParamListGenerateMethod,
+ mbMangledParamListGenerateMethod, 42, 4, this);
+ }
+ else if (token.compareTo("${mb_field_body_initialize}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMap(mbBodyInitGenerateMethod,
+ mbMangledBodyInitGenerateMethod, 8, 4, this);
+ }
+ else if (token.compareTo("${mb_field_size}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMapOrdinally(mbSizeGenerateMethod,
+ mbBitSizeGenerateMethod, 8, 4, this);
+ }
+ else if (token.compareTo("${mb_field_encode}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMapOrdinally(mbEncodeGenerateMethod,
+ mbBitEncodeGenerateMethod, 8, 4, this);
+ }
+ else if (token.compareTo("${mb_field_decode}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMapOrdinally(mbDecodeGenerateMethod,
+ mbBitDecodeGenerateMethod, 8, 4, this);
+ }
+ else if (token.compareTo("${mb_field_to_string}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMapOrdinally(mbToStringGenerateMethod,
+ mbBitToStringGenerateMethod, 8, 4, this);
+ }
+
+ // PropertyContentHeader classes
+ else if (token.compareTo("${pch_field_list_size}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMapOrdinally(pchSizeGenerateMethod,
+ pchBitSizeGenerateMethod, 12, 4, this);
+ }
+ else if (token.compareTo("${pch_field_list_payload}") == 0 )
+ {
+ codeSnippet = fieldMap.parseFieldMapOrdinally(pchEncodeGenerateMethod,
+ pchBitEncodeGenerateMethod, 12, 4, this);
+ }
+ else if (token.compareTo("${pch_field_list_decode}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMapOrdinally(pchDecodeGenerateMethod,
+ pchBitDecodeGenerateMethod, 12, 4, this);
+ }
+ else if (token.compareTo("${pch_get_compact_property_flags}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMapOrdinally(pchGetPropertyFlagsGenerateMethod,
+ pchBitGetPropertyFlagsGenerateMethod, 8, 4, this);
+ }
+ else if (token.compareTo("${pch_set_compact_property_flags}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMapOrdinally(pchSetPropertyFlagsGenerateMethod,
+ pchBitSetPropertyFlagsGenerateMethod, 8, 4, this);
+ }
+ else if (token.compareTo("${pch_field_clear_methods}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMap(pchClearGenerateMethod,
+ pchMangledClearGenerateMethod, 4, 4, this);
+ }
+ else if (token.compareTo("${pch_field_get_methods}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMap(pchGetGenerateMethod,
+ pchMangledGetGenerateMethod, 4, 4, this);
+ }
+ else if (token.compareTo("${pch_field_set_methods}") == 0)
+ {
+ codeSnippet = fieldMap.parseFieldMap(pchSetGenerateMethod,
+ pchMangledSetGenerateMethod, 4, 4, this);
+ }
+
+ 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
+
+ // Common methods
+
+ protected String generateFieldDeclaration(String codeType, AmqpField field,
+ AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag)
+ {
+ return Utils.createSpaces(indentSize) + "public " + codeType + " " + field.name +
+ "; // AMQP version(s): " + versionSet + cr;
+ }
+
+ protected String generateMangledFieldDeclaration(AmqpField field, int indentSize,
+ int tabSize, boolean nextFlag)
+ throws AmqpTypeMappingException
+ {
+ StringBuffer sb = new StringBuffer();
+ Iterator<String> dItr = field.domainMap.keySet().iterator();
+ int domainCntr = 0;
+ while (dItr.hasNext())
+ {
+ String domainName = dItr.next();
+ AmqpVersionSet versionSet = field.domainMap.get(domainName);
+ String codeType = getGeneratedType(domainName, versionSet.first());
+ sb.append(Utils.createSpaces(indentSize) + "public " + codeType + " " +
+ field.name + "_" + (domainCntr++) + "; // AMQP Version(s): " + versionSet +
+ cr);
+ }
+ return sb.toString();
+ }
+
+ protected String generateIndexInitializer(String mapName, AmqpOrdinalMap indexMap, int indentSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ StringBuffer sb = new StringBuffer();
+
+ Iterator<Integer> iItr = indexMap.keySet().iterator();
+ while (iItr.hasNext())
+ {
+ int index = iItr.next();
+ AmqpVersionSet versionSet = indexMap.get(index);
+ Iterator<AmqpVersion> vItr = versionSet.iterator();
+ while (vItr.hasNext())
+ {
+ AmqpVersion version = vItr.next();
+ sb.append(indent + mapName + ".put(\"" + version.toString() + "\", " + index + ");" + cr);
+ }
+ }
+ return sb.toString();
+ }
+
+ protected String generateRegistry(AmqpModel model, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ StringBuffer sb = new StringBuffer();
+
+ Iterator<String> cItr = model.classMap.keySet().iterator();
+ while (cItr.hasNext())
+ {
+ AmqpClass thisClass = model.classMap.get(cItr.next());
+ AmqpVersionSet firstVersionSet = thisClass.indexMap.get(thisClass.indexMap.firstKey());
+ boolean classVersionConsistentFlag = firstVersionSet.equals(globalVersionSet);
+ Iterator<String> mItr = thisClass.methodMap.keySet().iterator();
+ while (mItr.hasNext())
+ {
+ AmqpMethod method = thisClass.methodMap.get(mItr.next());
+ firstVersionSet = method.indexMap.get(method.indexMap.firstKey());
+ boolean methodVersionConsistentFlag = firstVersionSet.equals(globalVersionSet);
+ if (classVersionConsistentFlag && methodVersionConsistentFlag)
+ {
+ // Both class and method with consistent indeces for all known versions
+ int classIndex = thisClass.indexMap.firstKey();
+ int methodIndex = method.indexMap.firstKey();
+ sb.append(indent + "map.put(" + classIndex + "*1000 + " + methodIndex +
+ ", " + thisClass.name + Utils.firstUpper(method.name) + "Body.class);" + cr);
+ }
+ else
+ {
+ // Non-consistent indeces for all known versions - version-specific code required
+ sb.append(cr);
+
+ Iterator<AmqpVersion> vItr = globalVersionSet.iterator();
+ while (vItr.hasNext())
+ {
+ boolean first = true;
+ AmqpVersion version = vItr.next();
+
+ // Find class and method index for this version (if it exists)
+ try
+ {
+ int classIndex = findIndex(thisClass.indexMap, version);
+ int methodIndex = findIndex(method.indexMap, version);
+ sb.append(indent);
+ if (!first)
+ sb.append("else ");
+ sb.append("if ( major == " + version.getMajor() + " && minor == " +
+ version.getMinor() + " )" + cr);
+ sb.append(indent + tab + "map.put(" + classIndex + "*1000 + " +
+ methodIndex + ", " + thisClass.name + Utils.firstUpper(method.name) +
+ "Body.class);" + cr);
+ first = false;
+ }
+ catch (Exception e) {} // Ignore
+ }
+ sb.append(cr);
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ protected int findIndex(TreeMap<Integer, AmqpVersionSet> map, AmqpVersion version)
+ throws Exception
+ {
+ Iterator<Integer> iItr = map.keySet().iterator();
+ while (iItr.hasNext())
+ {
+ int index = iItr.next();
+ AmqpVersionSet versionSet = map.get(index);
+ if (versionSet.contains(version))
+ return index;
+ }
+ throw new Exception("Index not found");
+ }
+
+ // Methods for MessageBody classes
+ protected String generateMbGetMethod(String codeType, AmqpField field,
+ AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag)
+ {
+ return Utils.createSpaces(indentSize) + "public " + codeType + " get" +
+ Utils.firstUpper(field.name) + "() { return " + field.name + "; }" +
+ cr;
+ }
+
+ protected String generateMbMangledGetMethod(AmqpField field, int indentSize,
+ int tabSize, boolean nextFlag)
+ throws AmqpTypeMappingException
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ StringBuffer sb = new StringBuffer(cr);
+ sb.append(indent + "public <T> T get" + Utils.firstUpper(field.name) +
+ "(Class<T> classObj) throws AMQProtocolVersionException" + cr);
+ sb.append(indent + "{" + cr);
+ Iterator<String> dItr = field.domainMap.keySet().iterator();
+ int domainCntr = 0;
+ while (dItr.hasNext())
+ {
+ String domainName = dItr.next();
+ AmqpVersionSet versionSet = field.domainMap.get(domainName);
+ String codeType = getGeneratedType(domainName, versionSet.first());
+ sb.append(indent + tab + "if (classObj.equals(" + codeType +
+ ".class)) // AMQP Version(s): " + versionSet + cr);
+ sb.append(indent + tab + tab + "return (T)(Object)" + field.name + "_" +
+ (domainCntr++) + ";" + cr);
+ }
+ sb.append(indent + tab +
+ "throw new AMQProtocolVersionException(\"None of the AMQP versions defines \" +" +
+ cr + " \"field \\\"" + field.name +
+ "\\\" as domain \\\"\" + classObj.getName() + \"\\\".\");" + cr);
+ sb.append(indent + "}" + cr);
+ sb.append(cr);
+ return sb.toString();
+ }
+
+ protected String generateMbParamList(String codeType, AmqpField field,
+ AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag)
+ {
+ return Utils.createSpaces(indentSize) + codeType + " " + field.name +
+ (nextFlag ? "," : "") + " // AMQP version(s): " + versionSet + cr;
+ }
+
+ protected String generateMbMangledParamList(AmqpField field, int indentSize,
+ int tabSize, boolean nextFlag)
+ throws AmqpTypeMappingException
+ {
+ StringBuffer sb = new StringBuffer();
+ Iterator<String> dItr = field.domainMap.keySet().iterator();
+ int domainCntr = 0;
+ while (dItr.hasNext())
+ {
+ String domainName = dItr.next();
+ AmqpVersionSet versionSet = field.domainMap.get(domainName);
+ String codeType = getGeneratedType(domainName, versionSet.first());
+ sb.append(Utils.createSpaces(indentSize) + codeType + " " + field.name + "_" +
+ (domainCntr++) + (nextFlag ? "," : "") + " // AMQP version(s): " +
+ versionSet + cr);
+ }
+ return sb.toString();
+ }
+
+ protected String generateMbBodyInit(String codeType, AmqpField field,
+ AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag)
+ {
+ return Utils.createSpaces(indentSize) + "body." + field.name + " = " + field.name +
+ ";" + cr;
+ }
+
+ protected String generateMbMangledBodyInit(AmqpField field, int indentSize,
+ int tabSize, boolean nextFlag)
+ throws AmqpTypeMappingException
+ {
+ StringBuffer sb = new StringBuffer();
+ Iterator<String> dItr = field.domainMap.keySet().iterator();
+ int domainCntr = 0;
+ while (dItr.hasNext())
+ {
+ dItr.next();
+ sb.append(Utils.createSpaces(indentSize) + "body." + field.name + "_" + domainCntr +
+ " = " + field.name + "_" + (domainCntr++) + ";" + cr);
+ }
+ return sb.toString();
+ }
+
+ protected String generateMbFieldSize(String domainType, String fieldName,
+ int ordinal, int indentSize, int tabSize)
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append(Utils.createSpaces(indentSize) + "size += " +
+ typeMap.get(domainType).size.replaceAll("#", fieldName) +
+ "; // " + fieldName + ": " + domainType + cr);
+ return sb.toString();
+ }
+
+ protected String generateMbBitArrayFieldSize(ArrayList<String> bitFieldList,
+ int ordinal, int indentSize, int tabSize)
+ {
+ StringBuffer sb = new StringBuffer();
+ int numBytes = ((bitFieldList.size() - 1) / 8) + 1;
+ String comment = bitFieldList.size() == 1 ?
+ bitFieldList.get(0) + ": bit" :
+ "Combinded bits: " + bitFieldList;
+ sb.append(Utils.createSpaces(indentSize) + "size += " +
+ typeMap.get("bit").size.replaceAll("~", String.valueOf(numBytes)) +
+ "; // " + comment + cr);
+ return sb.toString();
+ }
+
+ protected String generateMbFieldEncode(String domain, String fieldName,
+ int ordinal, int indentSize, int tabSize)
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append(Utils.createSpaces(indentSize) +
+ typeMap.get(domain).encodeExpression.replaceAll("#", fieldName) +
+ "; // " + fieldName + ": " + domain + cr);
+ return sb.toString();
+ }
+
+ protected String generateMbBitFieldEncode(ArrayList<String> bitFieldList,
+ int ordinal, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String bitArrayName = "bitArray_" + ordinal;
+ StringBuffer sb = new StringBuffer(indent + "boolean[] " + bitArrayName +
+ " = new boolean[] { ");
+ for (int i=0; i<bitFieldList.size(); i++)
+ {
+ if (i != 0)
+ {
+ if ((i + 3) % 6 == 0)
+ sb.append("," + cr + indent + Utils.createSpaces(tabSize));
+ else
+ sb.append(", ");
+ }
+ sb.append(bitFieldList.get(i));
+ }
+ sb.append(" };" + cr);
+ sb.append(Utils.createSpaces(indentSize) +
+ typeMap.get("bit").encodeExpression.replaceAll("#", bitArrayName) + ";" + cr);
+ return sb.toString();
+ }
+
+ protected String generateMbFieldDecode(String domain, String fieldName,
+ int ordinal, int indentSize, int tabSize)
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append(Utils.createSpaces(indentSize) +
+ typeMap.get(domain).decodeExpression.replaceAll("#", fieldName) +
+ "; // " + fieldName + ": " + domain + cr);
+ return sb.toString();
+ }
+
+ protected String generateMbBitFieldDecode(ArrayList<String> bitFieldList,
+ int ordinal, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String bitArrayName = "bitArray_" + ordinal;
+ StringBuffer sb = new StringBuffer();
+ sb.append(indent +
+ typeMap.get("bit").decodeExpression.replaceAll("#", "boolean[] " + bitArrayName) +
+ ";" + cr);
+ for (int i=0; i<bitFieldList.size(); i++)
+ {
+ sb.append(indent + bitFieldList.get(i) + " = " + bitArrayName + "[" + i + "];" + cr);
+ }
+ return sb.toString();
+ }
+
+ protected String generateMbFieldToString(String domain, String fieldName,
+ int ordinal, int indentSize, int tabSize)
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append(Utils.createSpaces(indentSize) +
+ "buf.append(\" " + fieldName + ": \" + " + fieldName + ");" + cr);
+ return sb.toString();
+ }
+
+ protected String generateMbBitFieldToString(ArrayList<String> bitFieldList,
+ int ordinal, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ StringBuffer sb = new StringBuffer();
+ for (int i=0; i<bitFieldList.size(); i++)
+ {
+ String bitFieldName = bitFieldList.get(i);
+ sb.append(indent + "buf.append(\" " + bitFieldName + ": \" + " + bitFieldName +
+ ");" + cr);
+ }
+ return sb.toString();
+ }
+
+ // Methods for PropertyContentHeader classes
+
+ protected String generatePchClearMethod(String codeType, AmqpField field,
+ AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag)
+ throws AmqpTypeMappingException
+ {
+ // This is one case where the ordinal info is the only significant factor,
+ // the domain info plays no part. Defer to the mangled version; the code would be
+ // identical anyway...
+ return generatePchMangledClearMethod(field, indentSize, tabSize, nextFlag);
+ }
+
+ protected String generatePchMangledClearMethod(AmqpField field, int indentSize,
+ int tabSize, boolean nextFlag)
+ throws AmqpTypeMappingException
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ StringBuffer sb = new StringBuffer();
+ sb.append(indent + "public void clear" + Utils.firstUpper(field.name) +
+ "()" + cr);
+ sb.append(indent + "{" + cr);
+
+ // If there is more than one ordinal for this field or the ordinal does not
+ // apply to all known versions, then we need to generate version checks so
+ // we know which fieldProperty to clear.
+ if (field.ordinalMap.size() == 1 &&
+ field.ordinalMap.get(field.ordinalMap.firstKey()).size() == globalVersionSet.size())
+ {
+ int ordinal = field.ordinalMap.firstKey();
+ sb.append(indent + tab + "clearEncodedForm();" + cr);
+ sb.append(indent + tab + "propertyFlags[" + ordinal + "] = false;" + cr);
+ }
+ else
+ {
+ Iterator<Integer> oItr = field.ordinalMap.keySet().iterator();
+ while (oItr.hasNext())
+ {
+ int ordinal = oItr.next();
+ AmqpVersionSet versionSet = field.ordinalMap.get(ordinal);
+ sb.append(indent + tab);
+ if (ordinal != field.ordinalMap.firstKey())
+ sb.append("else ");
+ sb.append("if (");
+ sb.append(generateVersionCheck(versionSet));
+ sb.append(")" + cr);
+ sb.append(indent + tab + "{" + cr);
+ sb.append(indent + tab + tab + "clearEncodedForm();" + cr);
+ sb.append(indent + tab + tab + "propertyFlags[" + ordinal + "] = false;" + cr);
+ sb.append(indent + tab + "}" + cr);
+ }
+ }
+ sb.append(indent + "}" + cr);
+ sb.append(cr);
+ return sb.toString();
+ }
+
+ protected String generatePchGetMethod(String codeType, AmqpField field,
+ AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag)
+ throws AmqpTypeMappingException
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ StringBuffer sb = new StringBuffer(indent + "public " + codeType + " get" +
+ Utils.firstUpper(field.name) + "()" + cr);
+ sb.append(indent + "{" + cr);
+ sb.append(indent + tab + "decodeIfNecessary();" + cr);
+ sb.append(indent + tab + "return " + field.name + ";" + cr);
+ sb.append(indent + "}" + cr);
+ sb.append(cr);
+ return sb.toString();
+ }
+
+ protected String generatePchMangledGetMethod(AmqpField field, int indentSize,
+ int tabSize, boolean nextFlag)
+ throws AmqpTypeMappingException
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ StringBuffer sb = new StringBuffer(indent + "public <T> T get" +
+ Utils.firstUpper(field.name) +
+ "(Class<T> classObj) throws AMQProtocolVersionException" + cr);
+ sb.append(indent + "{" + cr);
+ Iterator<String> dItr = field.domainMap.keySet().iterator();
+ int domainCntr = 0;
+ while (dItr.hasNext())
+ {
+ String domainName = dItr.next();
+ AmqpVersionSet versionSet = field.domainMap.get(domainName);
+ String codeType = getGeneratedType(domainName, versionSet.first());
+ sb.append(indent + tab + "if (classObj.equals(" + codeType +
+ ".class)) // AMQP Version(s): " + versionSet + cr);
+ sb.append(indent + tab + "{" + cr);
+ sb.append(indent + tab + tab + "decodeIfNecessary();" + cr);
+ sb.append(indent + tab + tab + "return (T)(Object)" + field.name + "_" +
+ (domainCntr++) + ";" + cr);
+ sb.append(indent + tab + "}" + cr);
+ }
+ sb.append(indent + tab +
+ "throw new AMQProtocolVersionException(\"None of the AMQP versions defines \" +" +
+ cr + " \"field \\\"" + field.name +
+ "\\\" as domain \\\"\" + classObj.getName() + \"\\\".\");" + cr);
+ sb.append(indent + "}" + cr);
+ sb.append(cr);
+ return sb.toString();
+ }
+
+ protected String generatePchSetMethod(String codeType, AmqpField field,
+ AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag)
+ throws AmqpTypeMappingException
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ StringBuffer sb = new StringBuffer();
+ sb.append(indent + "public void set" + Utils.firstUpper(field.name) +
+ "(" + codeType + " " + field.name + ")" + cr);
+ sb.append(indent + "{" + cr);
+
+ // If there is more than one ordinal for this field or the ordinal does not
+ // apply to all known versions, then we need to generate version checks so
+ // we know which fieldProperty to clear.
+ if (field.ordinalMap.size() == 1 &&
+ field.ordinalMap.get(field.ordinalMap.firstKey()).size() == globalVersionSet.size())
+ {
+ int ordinal = field.ordinalMap.firstKey();
+ sb.append(indent + tab + "clearEncodedForm();" + cr);
+ sb.append(indent + tab + "propertyFlags[" + ordinal + "] = true;" + cr);
+ sb.append(indent + tab + "this." + field.name + " = " + field.name + ";" + cr);
+ }
+ else
+ {
+ Iterator<Integer> oItr = field.ordinalMap.keySet().iterator();
+ while (oItr.hasNext())
+ {
+ int ordinal = oItr.next();
+ AmqpVersionSet oVersionSet = field.ordinalMap.get(ordinal);
+ sb.append(indent + tab);
+ if (ordinal != field.ordinalMap.firstKey())
+ sb.append("else ");
+ sb.append("if (");
+ sb.append(generateVersionCheck(oVersionSet));
+ sb.append(")" + cr);
+ sb.append(indent + tab + "{" + cr);
+ sb.append(indent + tab + tab + "clearEncodedForm();" + cr);
+ sb.append(indent + tab + tab + "propertyFlags[" + ordinal + "] = true;" + cr);
+ sb.append(indent + tab + tab + "this." + field.name + " = " + field.name + ";" + cr);
+ sb.append(indent + tab + "}" + cr);
+ }
+ }
+ sb.append(indent + "}" + cr);
+ sb.append(cr);
+ return sb.toString();
+ }
+
+ protected String generatePchMangledSetMethod(AmqpField field, int indentSize,
+ int tabSize, boolean nextFlag)
+ throws AmqpTypeMappingException
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ StringBuffer sb = new StringBuffer();
+
+ Iterator<String> dItr = field.domainMap.keySet().iterator();
+ int domainCntr = 0;
+ while (dItr.hasNext())
+ {
+ String domainName = dItr.next();
+ AmqpVersionSet versionSet = field.domainMap.get(domainName);
+ String codeType = getGeneratedType(domainName, versionSet.first());
+
+ // Find ordinal with matching version
+ AmqpVersionSet commonVersionSet = new AmqpVersionSet();
+ Iterator<Integer> oItr = field.ordinalMap.keySet().iterator();
+ while (oItr.hasNext())
+ {
+ int ordinal = oItr.next();
+ AmqpVersionSet oVersionSet = field.ordinalMap.get(ordinal);
+ Iterator<AmqpVersion> vItr = oVersionSet.iterator();
+ boolean first = true;
+ while (vItr.hasNext())
+ {
+ AmqpVersion thisVersion = vItr.next();
+ if (versionSet.contains(thisVersion))
+ commonVersionSet.add(thisVersion);
+ }
+ if (!commonVersionSet.isEmpty())
+ {
+ sb.append(indent + "public void set" + Utils.firstUpper(field.name) +
+ "(" + codeType + " " + field.name + ")" + cr);
+ sb.append(indent + "{" + cr);
+ sb.append(indent + tab);
+ if (!first)
+ sb.append("else ");
+ sb.append("if (");
+ sb.append(generateVersionCheck(commonVersionSet));
+ sb.append(")" + cr);
+ sb.append(indent + tab + "{" + cr);
+ sb.append(indent + tab + tab + "clearEncodedForm();" + cr);
+ sb.append(indent + tab + tab + "propertyFlags[" + ordinal + "] = true;" + cr);
+ sb.append(indent + tab + tab + "this." + field.name + "_" + (domainCntr++) +
+ " = " + field.name + ";" + cr);
+ sb.append(indent + tab + "}" + cr);
+ sb.append(indent + "}" + cr);
+ sb.append(cr);
+ first = false;
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ protected String generatePchFieldSize(String domainType, String fieldName,
+ int ordinal, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ StringBuffer sb = new StringBuffer(indent + "if (propertyFlags[" + ordinal + "]) // " +
+ fieldName + ": " + domainType + cr);
+ sb.append(indent + Utils.createSpaces(tabSize) + "size += " +
+ typeMap.get(domainType).size.replaceAll("#", fieldName) + ";" + cr);
+ sb.append(cr);
+ return sb.toString();
+ }
+
+ protected String generatePchBitArrayFieldSize(ArrayList<String> bitFieldList,
+ int ordinal, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ String comment = bitFieldList.size() == 1 ?
+ bitFieldList.get(0) + ": bit" :
+ "Combinded bits: " + bitFieldList;
+ StringBuffer sb = new StringBuffer();
+
+ if (bitFieldList.size() == 1) // single bit
+ {
+ sb.append(indent + "if (propertyFlags[" + (ordinal - 1) + "]) // " + comment + cr);
+ sb.append(indent + tab + "size += " +
+ typeMap.get("bit").size.replaceAll("~", "1") + ";" + cr);
+ }
+ else // multiple bits - up to 8 are combined into one byte
+ {
+ String bitCntrName = "bitCntr_" + ordinal;
+ int startOrdinal = ordinal - bitFieldList.size();
+ sb.append(indent + "// " + comment + cr);
+ sb.append(indent + "int " + bitCntrName + " = 0;" + cr);
+ sb.append(indent + "for (int i=" + startOrdinal + "; i<" + ordinal + "; i++)" + cr);
+ sb.append(indent + "{" + cr);
+ sb.append(indent + tab + "if (propertyFlags[i])" + cr);
+ sb.append(indent + tab + tab + bitCntrName + "++;" + cr);
+ sb.append(indent + "}" + cr);
+ sb.append(indent + "size += " +
+ typeMap.get("bit").size.replaceAll("~", bitCntrName +
+ " > 0 ? ((" + bitCntrName + " - 1) / 8) + 1 : 0") + ";" + cr);
+ }
+ sb.append(cr);
+ return sb.toString();
+ }
+
+ protected String generatePchFieldEncode(String domainType, String fieldName,
+ int ordinal, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ StringBuffer sb = new StringBuffer();
+ sb.append(indent + "if (propertyFlags[" + ordinal + "]) // " + fieldName + ": " +
+ domainType + cr);
+ sb.append(indent + Utils.createSpaces(tabSize) +
+ typeMap.get(domainType).encodeExpression.replaceAll("#", fieldName) + ";" + cr);
+ sb.append(cr);
+ return sb.toString();
+ }
+
+ protected String generatePchBitFieldEncode(ArrayList<String> bitFieldList,
+ int ordinal, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ String comment = bitFieldList.size() == 1 ?
+ bitFieldList.get(0) + ": bit" :
+ "Combinded bits: " + bitFieldList;
+ StringBuffer sb = new StringBuffer();
+
+ if (bitFieldList.size() == 1) // single bit
+ {
+ sb.append(indent + "if (propertyFlags[" + (ordinal - 1) + "]) // " +
+ bitFieldList.get(0) + ": bit" + cr);
+ sb.append(indent + tab + typeMap.get("bit").encodeExpression.replaceAll("#",
+ "new boolean[] {" + bitFieldList.get(0) + "}") + ";" + cr);
+ }
+ else // multiple bits - up to 8 are combined into one byte
+ {
+ int startOrdinal = ordinal - bitFieldList.size();
+ String bitCntrName = "bitCntr" + startOrdinal;
+ sb.append(indent + "// " + comment + cr);
+ sb.append(indent + "int " + bitCntrName + " = 0;" + cr);
+ sb.append(indent + "for (int i=" + startOrdinal + "; i<=" + (ordinal - 1) + "; i++)" + cr);
+ sb.append(indent + "{" + cr);
+ sb.append(indent + tab + "if (propertyFlags[i])" + cr);
+ sb.append(indent + tab + tab + bitCntrName + "++;" + cr);
+ sb.append(indent + "}" + cr);
+ sb.append(indent + "if (" + bitCntrName + " > 0) // Are any of the property bits set?" + cr);
+ sb.append(indent + "{" + cr);
+ sb.append(indent + tab + "boolean[] fullBitArray = new boolean[] { ");
+ for (int i=0; i<bitFieldList.size(); i++)
+ {
+ if (i != 0)
+ sb.append(", ");
+ sb.append(bitFieldList.get(i));
+ }
+ sb.append(" };" + cr);
+ sb.append(indent + tab + "boolean[] flaggedBitArray = new boolean[" +bitCntrName +
+ "];" + cr);
+ sb.append(indent + tab + bitCntrName + " = 0;" + cr);
+ sb.append(indent + tab + "for (int i=" + startOrdinal + "; i<=" + (ordinal - 1) +
+ "; i++)" + cr);
+ sb.append(indent + tab + "{" + cr);
+ sb.append(indent + tab + tab+ "if (propertyFlags[i])" + cr);
+ sb.append(indent + tab + tab + tab + "flaggedBitArray[" + bitCntrName +
+ "++] = fullBitArray[i];" + cr);
+ sb.append(indent + tab + "}" + cr);
+ sb.append(indent + tab + typeMap.get("bit").encodeExpression.replaceAll("#",
+ "flaggedBitArray") + ";" + cr);
+ sb.append(indent + "}" + cr);
+ }
+ sb.append(cr);
+ return sb.toString();
+ }
+
+ protected String generatePchFieldDecode(String domainType, String fieldName,
+ int ordinal, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ StringBuffer sb = new StringBuffer();
+ sb.append(indent + "if (propertyFlags[" + ordinal + "]) // " + fieldName + ": " +
+ domainType + cr);
+ sb.append(indent + Utils.createSpaces(tabSize) +
+ typeMap.get(domainType).decodeExpression.replaceAll("#", fieldName) + ";" + cr);
+ sb.append(cr);
+ return sb.toString();
+ }
+
+ protected String generatePchBitFieldDecode(ArrayList<String> bitFieldList,
+ int ordinal, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ String comment = bitFieldList.size() == 1 ?
+ bitFieldList.get(0) + ": bit" :
+ "Combinded bits: " + bitFieldList;
+ StringBuffer sb = new StringBuffer();
+
+ if (bitFieldList.size() == 1) // single bit
+ {
+ sb.append(indent + "if (propertyFlags[" + (ordinal - 1) + "]) // " +
+ bitFieldList.get(0) + ": bit" + cr);
+ sb.append(indent + "{" + cr);
+ sb.append(indent + tab + typeMap.get("bit").decodeExpression.replaceAll("#",
+ "boolean[] flaggedBitArray") + ";" + cr);
+ sb.append(indent + tab + bitFieldList.get(0) + " = flaggedBitArray[0];" + cr);
+ sb.append(indent + "}" + cr);
+ }
+ else // multiple bits - up to 8 are combined into one byte
+ {
+ int startOrdinal = ordinal - bitFieldList.size();
+ String bitCntr = "bitCntr" + startOrdinal;
+ sb.append(indent + "// " + comment + cr);
+ sb.append(indent + "int " + bitCntr + " = 0;" + cr);
+ sb.append(indent + "for (int i=" + startOrdinal + "; i<=" + (ordinal - 1) + "; i++)" + cr);
+ sb.append(indent + "{" + cr);
+ sb.append(indent + tab + "if (propertyFlags[i])" + cr);
+ sb.append(indent + tab + tab + bitCntr + "++;" + cr);
+ sb.append(indent + "}" + cr);
+ sb.append(indent + "if (" + bitCntr + " > 0) // Are any of the property bits set?" + cr);
+ sb.append(indent + "{" + cr);
+ sb.append(indent + tab + typeMap.get("bit").decodeExpression.replaceAll("#",
+ "boolean[] flaggedBitArray") + ";" + cr);
+ sb.append(indent + tab + bitCntr + " = 0;" + cr);
+ for (int i=0; i<bitFieldList.size(); i++)
+ {
+ sb.append(indent + tab + "if (propertyFlags[" + (startOrdinal + i) + "])" + cr);
+ sb.append(indent + tab + tab + bitFieldList.get(i) + " = flaggedBitArray[" +
+ bitCntr + "++];" + cr);
+ }
+ sb.append(indent + "}" + cr);
+ }
+
+ sb.append(cr);
+ return sb.toString();
+ }
+
+ protected String generatePchGetPropertyFlags(String domainType, String fieldName,
+ int ordinal, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ StringBuffer sb = new StringBuffer();
+ int word = ordinal / 15;
+ int bit = 15 - (ordinal % 15);
+ sb.append(indent + "if (propertyFlags[" + ordinal + "]) // " + fieldName + ": " +
+ domainType + cr);
+ sb.append(indent + tab + "compactPropertyFlags[" + word + "] |= (1 << " +
+ bit + ");" + cr);
+ sb.append(cr);
+ return sb.toString();
+ }
+
+ protected String generatePchBitGetPropertyFlags(ArrayList<String> bitFieldList,
+ int ordinal, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ StringBuffer sb = new StringBuffer();
+ int startOrdinal = ordinal - bitFieldList.size();
+
+ for (int i=0; i<bitFieldList.size(); i++)
+ {
+ int thisOrdinal = startOrdinal + i;
+ int word = thisOrdinal / 15;
+ int bit = 15 - (thisOrdinal % 15);
+ sb.append(indent + "if (propertyFlags[" + thisOrdinal + "])" + cr);
+ sb.append(indent + tab + "compactPropertyFlags[" + word +
+ "] |= (1 << " + bit + ");" + cr);
+ }
+
+ sb.append(cr);
+ return sb.toString();
+ }
+
+ protected String generatePchSetPropertyFlags(String domainType, String fieldName,
+ int ordinal, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ StringBuffer sb = new StringBuffer();
+ int word = ordinal / 15;
+ int bit = 15 - (ordinal % 15);
+ sb.append(indent + "propertyFlags[" + ordinal + "] = (compactPropertyFlags[" +
+ word + "] & (1 << " + bit + ")) > 0;" + cr);
+ return sb.toString();
+ }
+
+ protected String generatePchBitSetPropertyFlags(ArrayList<String> bitFieldList,
+ int ordinal, int indentSize, int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ StringBuffer sb = new StringBuffer();
+ int startOrdinal = ordinal - bitFieldList.size();
+
+ for (int i=0; i<bitFieldList.size(); i++)
+ {
+ int thisOrdinal = startOrdinal + i;
+ int word = thisOrdinal / 15;
+ int bit = 15 - (thisOrdinal % 15);
+ sb.append(indent + "propertyFlags[" + thisOrdinal + "] = (compactPropertyFlags[" +
+ word + "] & (1 << " + bit + ")) > 0;" + cr);
+ }
+ return sb.toString();
+ }
+
+ private String generatePchPropertyFlagsDeclare()
+ {
+ return "private boolean[] propertyFlags;";
+ }
+
+ private String generatePchPropertyFlagsInitializer(int totNumFields)
+ {
+ return "propertyFlags = new boolean[" + totNumFields + "];";
+ }
+
+ private String generatePchCompactPropertyFlagsInitializer(AmqpClass thisClass, int indentSize,
+ int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ StringBuffer sb = new StringBuffer();
+ Iterator<AmqpVersion> vItr = globalVersionSet.iterator();
+ while (vItr.hasNext())
+ {
+ AmqpVersion version = vItr.next();
+ int numBytes = ((thisClass.fieldMap.getNumFields(version) - 1) / 15) + 1;
+
+ sb.append(indent);
+ if (!version.equals(globalVersionSet.first()))
+ sb.append("else ");
+ sb.append("if ( major == " + version.getMajor() + " && minor == " +
+ version.getMinor() + " )" + cr);
+ sb.append(indent + tab + "compactPropertyFlags = new int[] { ");
+ for (int i=0; i<numBytes; i++)
+ {
+ if (i!= 0)
+ sb.append(", ");
+ sb.append(i < numBytes - 1 ? "1" : "0"); // Set the "continue" flag where required
+ }
+ sb.append(" };" + cr);
+ }
+ return sb.toString();
+ }
+
+ private String generatePchCompactPropertyFlagsCheck(AmqpClass thisClass, int indentSize,
+ int tabSize)
+ {
+ String indent = Utils.createSpaces(indentSize);
+ String tab = Utils.createSpaces(tabSize);
+ StringBuffer sb = new StringBuffer();
+ Iterator<AmqpVersion> vItr = globalVersionSet.iterator();
+ while (vItr.hasNext())
+ {
+ AmqpVersion version = vItr.next();
+ int numFields = thisClass.fieldMap.getNumFields(version);
+ int numBytes = ((numFields - 1) / 15) + 1;
+
+ sb.append(indent);
+ if (!version.equals(globalVersionSet.first()))
+ sb.append("else ");
+ sb.append("if ( major == " + version.getMajor() + " && minor == " +
+ version.getMinor() + " && compactPropertyFlags.length != " + numBytes + " )" + cr);
+ sb.append(indent + tab +
+ "throw new AMQProtocolVersionException(\"Property flag array size mismatch:\" +" + cr);
+ sb.append(indent + tab + tab + "\"(Size found: \" + compactPropertyFlags.length +" + cr);
+ sb.append(indent + tab + tab + "\") Version " + version + " has " + numFields +
+ " fields which requires an int array of size " + numBytes + ".\");" + cr);
+ }
+ return sb.toString();
+ }
+
+ private String generateVersionCheck(AmqpVersionSet v)
+ throws AmqpTypeMappingException
+ {
+ StringBuffer sb = new StringBuffer();
+ AmqpVersion[] versionArray = new AmqpVersion[v.size()];
+ v.toArray(versionArray);
+ for (int i=0; i<versionArray.length; i++)
+ {
+ if (i != 0)
+ sb.append(" || ");
+ if (versionArray.length > 1)
+ sb.append("(");
+ sb.append("major == " + versionArray[i].getMajor() + " && minor == " +
+ versionArray[i].getMinor());
+ if (versionArray.length > 1)
+ sb.append(")");
+ }
+ return sb.toString();
+ }
+
+ private String camelCaseName(String name, boolean upperFirstFlag)
+ {
+ StringBuffer ccn = new StringBuffer();
+ String[] toks = name.split("[-_.\\ ]");
+ for (int i=0; i<toks.length; i++)
+ {
+ StringBuffer b = new StringBuffer(toks[i]);
+ if (upperFirstFlag || i>0)
+ b.setCharAt(0, Character.toUpperCase(toks[i].charAt(0)));
+ ccn.append(b);
+ }
+ return ccn.toString();
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/LanguageConverter.java b/gentools/org/apache/qpid/gentools/LanguageConverter.java
new file mode 100644
index 0000000000..b9a2c81aa3
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/LanguageConverter.java
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+public interface LanguageConverter
+{
+ public void setDomainMap(AmqpDomainMap domainMap);
+ public AmqpDomainMap getDomainMap();
+
+ public void setModel(AmqpModel model);
+ public AmqpModel getModel();
+
+ public String prepareClassName(String className);
+ public String prepareMethodName(String methodName);
+ public String prepareDomainName(String domainName);
+ public String getDomainType(String domainName, AmqpVersion version) throws AmqpTypeMappingException;
+ public String getGeneratedType(String domainName, AmqpVersion version) throws AmqpTypeMappingException;
+}
diff --git a/gentools/org/apache/qpid/gentools/Main.java b/gentools/org/apache/qpid/gentools/Main.java
new file mode 100644
index 0000000000..6deed79024
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/Main.java
@@ -0,0 +1,168 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+public class Main
+{
+ private DocumentBuilder docBuilder;
+ private AmqpVersionSet versionSet;
+ private Generator generator;
+ private AmqpDomainMap domainMap;
+ private AmqpModel model;
+
+ public Main() throws ParserConfigurationException
+ {
+ docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ versionSet = new AmqpVersionSet();
+ }
+
+ public void run(String[] args)
+ throws IOException,
+ SAXException,
+ AmqpParseException,
+ AmqpTypeMappingException,
+ AmqpTemplateException,
+ TargetDirectoryException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ File[] modelTemplateFiles = new File[]{};
+ File[] classTemplateFiles = new File[]{};
+ File[] methodTemplateFiles = new File[]{};
+ File[] fieldTemplateFiles = new File[]{};
+ String outDir = "out";
+
+ if (args[0].compareToIgnoreCase("-c") == 0)
+ {
+ // *** C++ generation ***
+ generator = new CppGenerator(versionSet);
+ domainMap = new AmqpDomainMap(generator);
+ model = new AmqpModel(generator);
+// classTemplateFiles = new File[]{ new File("templ.cpp/PropertyContentHeaderClass.tmpl") };
+// methodTemplateFiles = new File[]{ new File("templ.cpp/MethodBodyClass.tmpl") };
+ outDir += ".cpp";
+ }
+ else if (args[0].compareToIgnoreCase("-j") == 0)
+ {
+ // *** Java generation ***
+ generator = new JavaGenerator(versionSet);
+ domainMap = new AmqpDomainMap(generator);
+ model = new AmqpModel(generator);
+ modelTemplateFiles = new File[]
+ { new File("templ.java/MethodRegistryClass.tmpl") };
+ classTemplateFiles = new File[]
+ { new File("templ.java/PropertyContentHeaderClass.tmpl") };
+ methodTemplateFiles = new File[]
+ { new File("templ.java/MethodBodyClass.tmpl") };
+ outDir += ".java";
+ }
+ else
+ {
+ System.err.println("ERROR: Required argument specifying language (C++ [-c] or Java [-j]) missing.");
+ usage();
+ }
+
+ // 1. Suck in all the XML spec files provided on the command line.
+ for (int i=1; i<args.length; i++)
+ {
+ File f = new File(args[i]);
+ if (f.exists())
+ {
+ // 1a. Initialize dom
+ System.out.print("File: " + args[i]);
+ Document doc = docBuilder.parse(new File(args[i]));
+ Node amqpNode = Utils.findChild(doc, Utils.ELEMENT_AMQP);
+
+ // 1b. Extract version (major and minor) from the XML file
+ int major = Utils.getNamedIntegerAttribute(amqpNode, Utils.ATTRIBUTE_MAJOR);
+ int minor = Utils.getNamedIntegerAttribute(amqpNode, Utils.ATTRIBUTE_MINOR);
+ AmqpVersion version = new AmqpVersion(major, minor);
+ System.out.println(" Found version " + version.toString() + ".");
+ versionSet.add(version);
+
+ // 1c. Extract domains
+ domainMap.addFromNode(amqpNode, 0, version);
+
+ // 1d. Extract class/method/field heirarchy
+ model.addFromNode(amqpNode, 0, version);
+ }
+ else
+ System.err.println("ERROR: AMQP XML file \"" + args[i] + "\" not found.");
+ }
+// *** DEBUG INFO *** Uncomment bits from this block to see lots of stuff....
+// System.out.println();
+// System.out.println("*** Debug output ***");
+// System.out.println();
+// versionSet.print(System.out, 0, 2);
+// System.out.println();
+// domainMap.print(System.out, 0, 2);
+// System.out.println();
+// model.print(System.out, 0, 2);
+// System.out.println();
+// System.out.println("*** End debug output ***");
+// System.out.println();
+
+ // 2. Load up all templates
+ generator.initializeTemplates(modelTemplateFiles, classTemplateFiles,
+ methodTemplateFiles, fieldTemplateFiles);
+
+ // 3. Generate output
+ generator.generate(new File(outDir));
+
+ System.out.println("Files generated: " + generator.getNumberGeneratedFiles());
+ System.out.println("Done.");
+ }
+
+ public static void main(String[] args)
+ {
+ if (args.length < 2)
+ usage();
+ try { new Main().run(args); }
+ catch (IOException e) { e.printStackTrace(); }
+ catch (ParserConfigurationException e) { e.printStackTrace(); }
+ catch (SAXException e) { e.printStackTrace(); }
+ catch (AmqpParseException e) { e.printStackTrace(); }
+ catch (AmqpTypeMappingException e) { e.printStackTrace(); }
+ catch (AmqpTemplateException e) { e.printStackTrace(); }
+ catch (TargetDirectoryException e) { e.printStackTrace(); }
+ catch (IllegalAccessException e) { e.printStackTrace(); }
+ catch (InvocationTargetException e) { e.printStackTrace(); }
+ }
+
+ public static void usage()
+ {
+ System.out.println("AMQP XML generator v.0.0");
+ System.out.println("Usage: Main -c|-j filename [filename ...]");
+ System.out.println(" where -c flags C++ generation.");
+ System.out.println(" -j flags Java generation.");
+ System.out.println(" filename is a space-separated list of files to be parsed.");
+ System.exit(0);
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/NodeAware.java b/gentools/org/apache/qpid/gentools/NodeAware.java
new file mode 100644
index 0000000000..859caf1d7e
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/NodeAware.java
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import org.w3c.dom.Node;
+
+/**
+ * @author kpvdr
+ * Interface allowing the addition of elements from a node in the
+ * DOM of the AMQP specification. It is used by each of the model
+ * elements in a recursive fashion to build the model.
+ */
+public interface NodeAware
+{
+ /**
+ * Add a model element from the current DOM node. All model elements must implement
+ * this interface. If the node contains children that are also a part of the model,
+ * then this method is called on new instances of those model elements.
+ * @param n Node from which the current model element is to be added.
+ * @param o Ordinal value of the current model elemet.
+ * @param v Verion of the DOM from which the node comes.
+ * @throws AmqpParseException
+ * @throws AmqpTypeMappingException
+ */
+ public void addFromNode(Node n, int o, AmqpVersion v)
+ throws AmqpParseException, AmqpTypeMappingException;
+}
diff --git a/gentools/org/apache/qpid/gentools/Printable.java b/gentools/org/apache/qpid/gentools/Printable.java
new file mode 100644
index 0000000000..e3020a8965
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/Printable.java
@@ -0,0 +1,25 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import java.io.PrintStream;
+
+public interface Printable
+{
+ public void print(PrintStream out, int marginSize, int tabSize);
+}
diff --git a/gentools/org/apache/qpid/gentools/TargetDirectoryException.java b/gentools/org/apache/qpid/gentools/TargetDirectoryException.java
new file mode 100644
index 0000000000..00d6954686
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/TargetDirectoryException.java
@@ -0,0 +1,27 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+@SuppressWarnings("serial")
+public class TargetDirectoryException extends Exception
+{
+ public TargetDirectoryException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/gentools/org/apache/qpid/gentools/Utils.java b/gentools/org/apache/qpid/gentools/Utils.java
new file mode 100644
index 0000000000..2791f31662
--- /dev/null
+++ b/gentools/org/apache/qpid/gentools/Utils.java
@@ -0,0 +1,210 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.gentools;
+
+import org.w3c.dom.Attr;
+//import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class Utils
+{
+ public final static String fileSeparator = System.getProperty("file.separator");
+ public final static String lineSeparator = System.getProperty("line.separator");
+
+ public final static String ATTRIBUTE_NAME = "name";
+ public final static String ATTRIBUTE_MAJOR = "major";
+ public final static String ATTRIBUTE_MINOR = "minor";
+ public final static String ATTRIBUTE_INDEX = "index";
+ public final static String ATTRIBUTE_LABEL = "label";
+ public final static String ATTRIBUTE_SYNCHRONOUS = "synchronous";
+ 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_TYPE = "type"; // For compatibility with AMQP 8.0
+
+ public final static String ELEMENT_AMQP = "amqp";
+ public final static String ELEMENT_CLASS = "class";
+ public final static String ELEMENT_DOMAIN = "domain";
+ public final static String ELEMENT_METHOD = "method";
+ public final static String ELEMENT_FIELD = "field";
+ public final static String ELEMENT_VERSION = "version";
+
+ // Version functions
+
+// public static String createVersionKey(int major, int minor)
+// {
+// return major + "-" + minor;
+// }
+
+ // Attribute functions
+
+ public static String getNamedAttribute(Node n, String attrName) throws AmqpParseException
+ {
+ NamedNodeMap nnm = n.getAttributes();
+ if (nnm == null)
+ throw new AmqpParseException("Node \"" + n.getNodeName() + "\" has no attributes.");
+ Attr a = (Attr)nnm.getNamedItem(attrName);
+ if (a == null)
+ throw new AmqpParseException("Node \"" + n.getNodeName() + "\" has no attribute \"" + attrName + "\".");
+ return a.getNodeValue();
+ }
+
+ public static int getNamedIntegerAttribute(Node n, String attrName) throws AmqpParseException
+ {
+ return Integer.parseInt(getNamedAttribute(n, attrName));
+ }
+
+// public static boolean containsAttribute(Node n, String attrName)
+// {
+// try { getNamedAttribute(n, attrName); }
+// catch (AmqpParseException e) { return false; }
+// return true;
+// }
+//
+// public static boolean containsAttributeValue(Node n, String attrName, String attrValue)
+// {
+// try { return getNamedAttribute(n, attrName).compareTo(attrValue) == 0; }
+// catch (AmqpParseException e) { return false; }
+// }
+//
+// public static boolean containsAttributeValue(Node n, String attrName, int attrValue)
+// {
+// try { return Integer.parseInt(getNamedAttribute(n, attrName)) == attrValue; }
+// catch (AmqpParseException e) { return false; }
+// }
+//
+// public static void createNamedAttribute(Document doc, NamedNodeMap nnm, String attrName, String attrValue)
+// {
+// Attr a = doc.createAttribute(attrName);
+// a.setNodeValue(attrValue);
+// nnm.setNamedItem(a);
+// }
+//
+// public static void createNamedAttribute(Document doc, NamedNodeMap nnm, String attrName, int attrValue)
+// {
+// createNamedAttribute(doc, nnm, attrName, Integer.toString(attrValue));
+// }
+//
+// public static void createNamedAttribute(Node n, String attrName, String attrValue)
+// {
+// createNamedAttribute(n.getOwnerDocument(), n.getAttributes(), attrName, attrValue);
+// }
+//
+// public static void createNamedAttribute(Node n, String attrName, int attrValue)
+// {
+// createNamedAttribute(n, attrName, Integer.toString(attrValue));
+// }
+
+ // Element functions
+
+ public static Node findChild(Node n, String eltName) throws AmqpParseException
+ {
+ NodeList nl = n.getChildNodes();
+ for (int i=0; i<nl.getLength(); i++)
+ {
+ Node cn = nl.item(i);
+ if (cn.getNodeName().compareTo(eltName) == 0)
+ return cn;
+ }
+ throw new AmqpParseException("Node \"" + n.getNodeName() +
+ "\" does not contain child element \"" + eltName + "\".");
+ }
+
+// public static boolean containsChild(Node n, String eltName)
+// {
+// try { findChild(n, eltName); }
+// catch(AmqpParseException e) { return false; }
+// return true;
+// }
+//
+// public static Node findNamedChild(Node n, String eltName, String nameAttrVal) throws AmqpParseException
+// {
+// NodeList nl = n.getChildNodes();
+// for (int i=0; i<nl.getLength(); i++)
+// {
+// Node cn = nl.item(i);
+// if (cn.getNodeName().compareTo(eltName) == 0)
+// if (Utils.getNamedAttribute(cn, "name").compareTo(nameAttrVal) == 0)
+// return cn;
+// }
+// throw new AmqpParseException("Node \"" + n.getNodeName() +
+// "\" does not contain child element \"" + eltName + "\".");
+// }
+//
+// public static boolean containsNamedChild(Node n, String eltName, String nameAttrVal)
+// {
+// try { findNamedChild(n, eltName, nameAttrVal); }
+// catch(AmqpParseException e) { return false; }
+// return true;
+// }
+
+ // Map functions
+
+
+// protected static Vector<AmqpVersion> buildVersionMap(Node n)throws AmqpParseException
+// {
+// Vector<AmqpVersion> versionList = new Vector<AmqpVersion>();
+// NodeList nl = n.getChildNodes();
+// for (int i=0; i<nl.getLength(); i++)
+// {
+// Node cn = nl.item(i);
+// if (cn.getNodeName().compareTo(AmqpXmlParser.ELEMENT_VERSION) == 0)
+// {
+// AmqpVersion ver = new AmqpVersion();
+// ver.major = Utils.getNamedIntegerAttribute(cn, "major");
+// ver.minor = Utils.getNamedIntegerAttribute(cn, "minor");
+// versionList.add(ver);
+// }
+// }
+// return versionList;
+// }
+//
+// protected static Vector<AmqpField> buildFieldMap(Node n)throws AmqpParseException
+// {
+// Vector<AmqpField> fieldList = new Vector<AmqpField>();
+// NodeList nl = n.getChildNodes();
+// for (int i=0; i<nl.getLength(); i++)
+// {
+// Node c = nl.item(i);
+// if (c.getNodeName().compareTo(AmqpXmlParser.ELEMENT_FIELD) == 0)
+// fieldList.add(new AmqpField(c));
+// }
+// return fieldList;
+// }
+
+ // String functions
+
+ public static String firstUpper(String str)
+ {
+ if (!Character.isLowerCase(str.charAt(0)))
+ return str;
+ StringBuffer sb = new StringBuffer(str);
+ sb.setCharAt(0, Character.toUpperCase(str.charAt(0)));
+ return sb.toString();
+ }
+
+ public static String createSpaces(int cnt)
+ {
+ StringBuffer sb = new StringBuffer();
+ for (int i=0; i<cnt; i++)
+ sb.append(' ');
+ return sb.toString();
+ }
+}