diff options
author | Robert Greig <rgreig@apache.org> | 2006-12-28 00:32:45 +0000 |
---|---|---|
committer | Robert Greig <rgreig@apache.org> | 2006-12-28 00:32:45 +0000 |
commit | 26999d9fcb1aed68d2345d68819edf2d4c54821f (patch) | |
tree | 16d5acd41bede65bc7589848faa5c19a3ee681b9 | |
parent | 7e64cb6cb3f3668fe87984715e7c2675c9bf7946 (diff) | |
download | qpid-python-26999d9fcb1aed68d2345d68819edf2d4c54821f.tar.gz |
Merge up to trunk rev 490505
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/new_persistence@490614 13f79535-47bb-0310-9956-ffa450edef68
52 files changed, 4102 insertions, 1440 deletions
diff --git a/gentools/org/apache/qpid/gentools/AmqpClassMap.java b/gentools/org/apache/qpid/gentools/AmqpClassMap.java deleted file mode 100644 index e86495f27e..0000000000 --- a/gentools/org/apache/qpid/gentools/AmqpClassMap.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * - * 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 deleted file mode 100644 index e313772a83..0000000000 --- a/gentools/org/apache/qpid/gentools/AmqpDomain.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - * 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/AmqpMethod.java b/gentools/org/apache/qpid/gentools/AmqpMethod.java deleted file mode 100644 index 37c254e32c..0000000000 --- a/gentools/org/apache/qpid/gentools/AmqpMethod.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * - * 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 deleted file mode 100644 index 07e236d2cd..0000000000 --- a/gentools/org/apache/qpid/gentools/AmqpMethodMap.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * - * 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/AmqpOrdinalMap.java b/gentools/org/apache/qpid/gentools/AmqpOrdinalMap.java deleted file mode 100644 index a340376d0e..0000000000 --- a/gentools/org/apache/qpid/gentools/AmqpOrdinalMap.java +++ /dev/null @@ -1,9 +0,0 @@ -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 deleted file mode 100644 index 2a85001f99..0000000000 --- a/gentools/org/apache/qpid/gentools/AmqpParseException.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * - * 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 deleted file mode 100644 index c0a3edb207..0000000000 --- a/gentools/org/apache/qpid/gentools/AmqpTemplateException.java +++ /dev/null @@ -1,10 +0,0 @@ -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 deleted file mode 100644 index b2304344c6..0000000000 --- a/gentools/org/apache/qpid/gentools/AmqpTypeMappingException.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * - * 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 deleted file mode 100644 index f3f4f5833b..0000000000 --- a/gentools/org/apache/qpid/gentools/AmqpVersion.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * 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 deleted file mode 100644 index 608a319146..0000000000 --- a/gentools/org/apache/qpid/gentools/AmqpVersionSet.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * 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 deleted file mode 100644 index 3405e48984..0000000000 --- a/gentools/org/apache/qpid/gentools/CppGenerator.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * - * 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/LanguageConverter.java b/gentools/org/apache/qpid/gentools/LanguageConverter.java deleted file mode 100644 index b9a2c81aa3..0000000000 --- a/gentools/org/apache/qpid/gentools/LanguageConverter.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * - * 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 deleted file mode 100644 index 6deed79024..0000000000 --- a/gentools/org/apache/qpid/gentools/Main.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * - * 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/Printable.java b/gentools/org/apache/qpid/gentools/Printable.java deleted file mode 100644 index e3020a8965..0000000000 --- a/gentools/org/apache/qpid/gentools/Printable.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * - * 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 deleted file mode 100644 index 00d6954686..0000000000 --- a/gentools/org/apache/qpid/gentools/TargetDirectoryException.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * - * 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 deleted file mode 100644 index 2791f31662..0000000000 --- a/gentools/org/apache/qpid/gentools/Utils.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * - * 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(); - } -} diff --git a/gentools/org/apache/qpid/gentools/AmqpClass.java b/gentools/src/org/apache/qpid/gentools/AmqpClass.java index 4ded7db94a..3f66e15567 100644 --- a/gentools/org/apache/qpid/gentools/AmqpClass.java +++ b/gentools/src/org/apache/qpid/gentools/AmqpClass.java @@ -1,24 +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. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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; @@ -26,26 +28,26 @@ import org.w3c.dom.NodeList; public class AmqpClass implements Printable, NodeAware { public LanguageConverter converter; - public AmqpVersionSet versionList; + public AmqpVersionSet versionSet; public AmqpFieldMap fieldMap; public AmqpMethodMap methodMap; public String name; - public AmqpOrdinalMap indexMap; + public AmqpOrdinalVersionMap indexMap; public AmqpClass(String name, LanguageConverter converter) { this.name = name; this.converter = converter; - versionList = new AmqpVersionSet(); + versionSet = new AmqpVersionSet(); fieldMap = new AmqpFieldMap(); methodMap = new AmqpMethodMap(); - indexMap = new AmqpOrdinalMap(); + indexMap = new AmqpOrdinalVersionMap(); } public void addFromNode(Node classNode, int ordinal, AmqpVersion version) throws AmqpParseException, AmqpTypeMappingException { - versionList.add(version); + versionSet.add(version); int index = Utils.getNamedIntegerAttribute(classNode, "index"); AmqpVersionSet versionSet = indexMap.get(index); if (versionSet != null) @@ -92,27 +94,23 @@ public class AmqpClass implements Printable, NodeAware { String margin = Utils.createSpaces(marginSize); String tab = Utils.createSpaces(tabSize); - out.println(margin + "[C] " + name + ": " + versionList); + out.println(margin + "[C] " + name + ": " + versionSet); - Iterator<Integer> iItr = indexMap.keySet().iterator(); - while (iItr.hasNext()) + for (Integer thisIndex : indexMap.keySet()) { - int index = iItr.next(); - AmqpVersionSet indexVersionSet = indexMap.get(index); - out.println(margin + tab + "[I] " + index + indexVersionSet); + AmqpVersionSet indexVersionSet = indexMap.get(thisIndex); + out.println(margin + tab + "[I] " + thisIndex + indexVersionSet); } - Iterator<String> sItr = fieldMap.keySet().iterator(); - while (sItr.hasNext()) + for (String thisFieldName : fieldMap.keySet()) { - AmqpField thisField = fieldMap.get(sItr.next()); + AmqpField thisField = fieldMap.get(thisFieldName); thisField.print(out, marginSize + tabSize, tabSize); } - sItr = methodMap.keySet().iterator(); - while (sItr.hasNext()) + for (String thisMethodName : methodMap.keySet()) { - AmqpMethod thisMethod = methodMap.get(sItr.next()); + AmqpMethod thisMethod = methodMap.get(thisMethodName); thisMethod.print(out, marginSize + tabSize, tabSize); } } diff --git a/gentools/src/org/apache/qpid/gentools/AmqpClassMap.java b/gentools/src/org/apache/qpid/gentools/AmqpClassMap.java new file mode 100644 index 0000000000..01d4df283b --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpClassMap.java @@ -0,0 +1,29 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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/src/org/apache/qpid/gentools/AmqpConstant.java b/gentools/src/org/apache/qpid/gentools/AmqpConstant.java new file mode 100644 index 0000000000..6ccd2dbf99 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpConstant.java @@ -0,0 +1,205 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.TreeMap; + +/** + * @author kpvdr + * Class to represent the <constant> declaration within the AMQP specification. + * Currently, only integer values exist within the specification, however looking forward + * to other possible types in the future, string and double types are also supported. + * + * The <constant> declaration in the specification contains only two attributes: + * name and value. + * + * The value of the constant is mapped against the version(s) for which the name is defined. + * This allows for a change in the value rather than the name only from one version to the next. + */ +@SuppressWarnings("serial") +public class AmqpConstant extends TreeMap<String, AmqpVersionSet> + implements Printable, VersionConsistencyCheck, Comparable<AmqpConstant> +{ + /** + * Constant name as defined by the name attribute of the <constant> declaration. + */ + protected String name; + + /** + * Set of versions for which this constant name is defined. + */ + protected AmqpVersionSet versionSet; + + /** + * Constructor + * @param name Constant name as defined by the name attribute of the <constant> declaration. + * @param value Constant value as defined by the value attribute of the <constant> declaration. + * @param version AMQP version for which this constant is defined + */ + public AmqpConstant (String name, String value, AmqpVersion version) + { + this.name = name; + versionSet = new AmqpVersionSet(version); + AmqpVersionSet valueVersionSet = new AmqpVersionSet(version); + put(value, valueVersionSet); + } + + /** + * Constructor + * @param name Constant name as defined by the name attribute of the <constant> declaration. + * @param value Constant value as defined by the value attribute of the <constant> declaration. + * @param version AMQP version for which this constant is defined + */ + public AmqpConstant (String name, int value, AmqpVersion version) + { + this.name = name; + versionSet = new AmqpVersionSet(version); + AmqpVersionSet valueVersionSet = new AmqpVersionSet(version); + put(String.valueOf(value), valueVersionSet); + } + + /** + * Constructor + * @param name Constant name as defined by the name attribute of the <constant> declaration. + * @param value Constant value as defined by the value attribute of the <constant> declaration. + * @param version AMQP version for which this constant is defined + */ + public AmqpConstant (String name, double value, AmqpVersion version) + { + this.name = name; + versionSet = new AmqpVersionSet(version); + AmqpVersionSet valueVersionSet = new AmqpVersionSet(version); + put(String.valueOf(value), valueVersionSet); + } + + /** + * Get the name of this constant. + * @return Name of this constant, being the name attribute of the <constant> declaration + * represented by this class. + */ + public String getName() + { + return name; + } + + /** + * Get the value of this constant as a String. + * @param version AMQP version for which this value is required. + * @return Value of this constant, being the value attribute of the <constant> declaration + * represented by this class. + * @throws AmqpTypeMappingException when a value is requested for a version for which it is not + * defined in the AMQP specifications. + */ + public String getStringValue(AmqpVersion version) + throws AmqpTypeMappingException + { + for (String thisValue : keySet()) + { + AmqpVersionSet versionSet = get(thisValue); + if (versionSet.contains(version)) + return thisValue; + } + throw new AmqpTypeMappingException("Unable to find value for constant \"" + name + + "\" for version " + version.toString() + "."); + } + + /** + * Get the value of this constant as an integer. + * @param version AMQP version for which this value is required. + * @return Value of this constant, being the value attribute of the <constant> declaration + * represented by this class. + * @throws AmqpTypeMappingException when a value is requested for a version for which it is not + * defined in the AMQP specifications. + */ + public int getIntegerValue(AmqpVersion version) + throws AmqpTypeMappingException + { + return Integer.parseInt(getStringValue(version)); + } + + /** + * Get the value of this constant as a double. + * @param version AMQP version for which this value is required. + * @return Value of this constant, being the value attribute of the <constant> declaration + * represented by this class. + * @throws AmqpTypeMappingException when a value is requested for a version for which it is not + * defined in the AMQP specifications. + */ + public double getDoubleValue(AmqpVersion version) + throws AmqpTypeMappingException + { + return Double.parseDouble(getStringValue(version)); + } + + /** + * Get the version set for this constant. It contains the all the versions for which this + * constant name exists. + * @return Set of versions for which this constant exists. + */ + public AmqpVersionSet getVersionSet() + { + return versionSet; + } + + /* (non-Javadoc) + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + + public int compareTo(AmqpConstant other) + { + int res = name.compareTo(other.name); + if (res != 0) + return res; + return versionSet.compareTo(other.versionSet); + } + + /* (non-Javadoc) + * @see org.apache.qpid.gentools.VersionConsistencyCheck#isVersionConsistent(org.apache.qpid.gentools.AmqpVersionSet) + */ + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + if (size() != 1) + return false; + return get(firstKey()).equals(globalVersionSet); + } + + /* (non-Javadoc) + * @see org.apache.qpid.gentools.Printable#print(java.io.PrintStream, int, int) + */ + public void print(PrintStream out, int marginSize, int tabSize) + { + String margin = Utils.createSpaces(marginSize); + String tab = Utils.createSpaces(tabSize); + if (size() == 1) + { + out.println(margin + tab + "[C] " + name + " = \"" + firstKey() + "\" " + versionSet); + } + else + { + out.println(margin + tab + "[C] " + name + ": " + versionSet); + for (String thisValue : keySet()) + { + out.println(margin + tab + tab + "= \"" + thisValue + "\" " + get(thisValue)); + } + } + } +} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpConstantSet.java b/gentools/src/org/apache/qpid/gentools/AmqpConstantSet.java new file mode 100644 index 0000000000..732ef46635 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpConstantSet.java @@ -0,0 +1,132 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.TreeSet; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * @author kpvdr + * This class implements a set collection for {@link #AmqpConstant AmqpConstant} objects, being the collection + * of constants accumulated from various AMQP specification files processed. Each name occurs once only in the set. + * The {@link #AmqpConstant AmqpConstant} objects (derived from {@link java.util#TreeMap TreeMap}) keep track of + * the value and version(s) assigned to this name. + */ +@SuppressWarnings("serial") +public class AmqpConstantSet extends TreeSet<AmqpConstant> implements Printable, NodeAware, Comparable<AmqpConstantSet> +{ + public LanguageConverter converter; + + public AmqpConstantSet(LanguageConverter converter) + { + this.converter = converter; + this.converter.setConstantSet(this); + } + + /* (non-Javadoc) + * @see org.apache.qpid.gentools.NodeAware#addFromNode(org.w3c.dom.Node, int, org.apache.qpid.gentools.AmqpVersion) + */ + public void addFromNode(Node node, int ordinal, AmqpVersion version) + throws AmqpParseException, AmqpTypeMappingException + { + NodeList nodeList = node.getChildNodes(); + for (int i=0; i<nodeList.getLength(); i++) + { + Node childNode = nodeList.item(i); + if (childNode.getNodeName().compareTo(Utils.ELEMENT_CONSTANT) == 0) + { + String name = converter.prepareDomainName(Utils.getNamedAttribute(childNode, Utils.ATTRIBUTE_NAME)); + String value = Utils.getNamedAttribute(childNode, Utils.ATTRIBUTE_VALUE); + // Find this name in the existing set of objects + boolean foundName = false; + Iterator<AmqpConstant> cItr = iterator(); + while (cItr.hasNext() && !foundName) + { + AmqpConstant thisConstant = cItr.next(); + if (name.compareTo(thisConstant.name) == 0) + { + foundName = true; + thisConstant.versionSet.add(version); + // Now, find the value in the map + boolean foundValue = false; + for (String thisValue : thisConstant.keySet()) + { + if (value.compareTo(thisValue) == 0) + { + foundValue = true; + // Add this version to existing version set. + AmqpVersionSet versionSet = thisConstant.get(thisValue); + versionSet.add(version); + } + } + // Check that the value was found - if not, add it + if (!foundValue) + { + thisConstant.put(value, new AmqpVersionSet(version)); + } + } + } + // Check that the name was found - if not, add it + if (!foundName) + { + add(new AmqpConstant(name, value, version)); + } + } + } + } + + /* (non-Javadoc) + * @see org.apache.qpid.gentools.Printable#print(java.io.PrintStream, int, int) + */ + public void print(PrintStream out, int marginSize, int tabSize) + { + out.println(Utils.createSpaces(marginSize) + "Constants: "); + for (AmqpConstant thisAmqpConstant : this) + { + thisAmqpConstant.print(out, marginSize, tabSize); + } + } + + /* (non-Javadoc) + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public int compareTo(AmqpConstantSet other) + { + int res = size() - other.size(); + if (res != 0) + return res; + Iterator<AmqpConstant> cItr = iterator(); + Iterator<AmqpConstant> oItr = other.iterator(); + while (cItr.hasNext() && oItr.hasNext()) + { + AmqpConstant constant = cItr.next(); + AmqpConstant oConstant = oItr.next(); + res = constant.compareTo(oConstant); + if (res != 0) + return res; + } + return 0; + } +} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpDomain.java b/gentools/src/org/apache/qpid/gentools/AmqpDomain.java new file mode 100644 index 0000000000..4796f31fb3 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpDomain.java @@ -0,0 +1,78 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.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 version) + throws AmqpTypeMappingException + { + for (String thisDomainType : keySet()) + { + AmqpVersionSet versionSet = get(thisDomainType); + if (versionSet.contains(version)) + return thisDomainType; + } throw new AmqpTypeMappingException("Unable to find version " + version + "."); + } + + 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 + ":"); + + for (String thisDomainType : keySet()) + { + AmqpVersionSet vs = get(thisDomainType); + out.println(margin + tab + thisDomainType + " : " + vs.toString()); + } + } +} diff --git a/gentools/org/apache/qpid/gentools/AmqpDomainMap.java b/gentools/src/org/apache/qpid/gentools/AmqpDomainMap.java index 88cc9a17b3..a2a9ce3aa9 100644 --- a/gentools/org/apache/qpid/gentools/AmqpDomainMap.java +++ b/gentools/src/org/apache/qpid/gentools/AmqpDomainMap.java @@ -1,24 +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. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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; @@ -82,34 +84,34 @@ public class AmqpDomainMap extends TreeMap<String, AmqpDomain> implements Printa } } - public String getDomainType(String domainName, AmqpVersion v) + public String getDomainType(String domainName, AmqpVersion version) throws AmqpTypeMappingException { - AmqpDomain domain = get(domainName); + AmqpDomain domainType = 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); + if (domainType == null) + { + return domainName; + } try { - return domain.getDomainType(v); + return domainType.getDomainType(version); } catch (AmqpTypeMappingException e) { throw new AmqpTypeMappingException("Unable to find domain type for domain \"" + domainName + - "\" version " + v + "."); + "\" version " + version + "."); } } public void print(PrintStream out, int marginSize, int tabSize) { - Iterator<String> i = keySet().iterator(); - out.println(Utils.createSpaces(marginSize) + "Domain Map:"); - while (i.hasNext()) + out.println(Utils.createSpaces(marginSize) + "Domain Map:"); + for (String thisDomainName : keySet()) { - String domainName = i.next(); - AmqpDomain domain = get(domainName); + AmqpDomain domain = get(thisDomainName); domain.print(out, marginSize + tabSize, tabSize); } } diff --git a/gentools/src/org/apache/qpid/gentools/AmqpDomainVersionMap.java b/gentools/src/org/apache/qpid/gentools/AmqpDomainVersionMap.java new file mode 100644 index 0000000000..6cd632a9d6 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpDomainVersionMap.java @@ -0,0 +1,34 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 AmqpDomainVersionMap extends TreeMap<String, AmqpVersionSet> implements VersionConsistencyCheck +{ + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + if (size() != 1) + return false; + return get(firstKey()).equals(globalVersionSet); + } +} diff --git a/gentools/org/apache/qpid/gentools/AmqpField.java b/gentools/src/org/apache/qpid/gentools/AmqpField.java index a46c424887..8e87641445 100644 --- a/gentools/org/apache/qpid/gentools/AmqpField.java +++ b/gentools/src/org/apache/qpid/gentools/AmqpField.java @@ -1,35 +1,36 @@ /* * - * 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. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 class AmqpField implements Printable, NodeAware, VersionConsistencyCheck { public LanguageConverter converter; public AmqpVersionSet versionSet; - public TreeMap<String, AmqpVersionSet> domainMap; - public AmqpOrdinalMap ordinalMap; + public AmqpDomainVersionMap domainMap; + public AmqpOrdinalVersionMap ordinalMap; public String name; public AmqpField(String name, LanguageConverter converter) @@ -37,8 +38,8 @@ public class AmqpField implements Printable, NodeAware this.name = name; this.converter = converter; versionSet = new AmqpVersionSet(); - domainMap = new TreeMap<String, AmqpVersionSet>(); - ordinalMap = new AmqpOrdinalMap(); + domainMap = new AmqpDomainVersionMap(); + ordinalMap = new AmqpOrdinalVersionMap(); } public void addFromNode(Node fieldNode, int ordinal, AmqpVersion version) @@ -71,18 +72,16 @@ public class AmqpField implements Printable, NodeAware thisVersionList.add(version); } - public boolean isCodeTypeConsistent(Generator generator) + public boolean isCodeTypeConsistent(LanguageConverter converter) 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()) + for (String thisDomainName : domainMap.keySet()) { - String domainName = itr.next(); - AmqpVersionSet versionSet = domainMap.get(domainName); - String codeType = generator.getGeneratedType(domainName, versionSet.first()); + AmqpVersionSet versionSet = domainMap.get(thisDomainName); + String codeType = converter.getGeneratedType(thisDomainName, versionSet.first()); if (!codeTypeList.contains(codeType)) codeTypeList.add(codeType); } @@ -99,9 +98,10 @@ public class AmqpField implements Printable, NodeAware // 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(); + for (String thisDomainName : domainMap.keySet()) + { + vCntr += domainMap.get(thisDomainName).size(); + } return vCntr == generator.globalVersionSet.size(); } @@ -110,20 +110,27 @@ public class AmqpField implements Printable, NodeAware String margin = Utils.createSpaces(marginSize); out.println(margin + "[F] " + name + ": " + versionSet); - Iterator<Integer> iItr = ordinalMap.keySet().iterator(); - while (iItr.hasNext()) + for (Integer thisOrdinal : ordinalMap.keySet()) { - Integer ordinalValue = iItr.next(); - AmqpVersionSet versionList = ordinalMap.get(ordinalValue); - out.println(margin + " [O] " + ordinalValue + " : " + versionList.toString()); + AmqpVersionSet versionList = ordinalMap.get(thisOrdinal); + out.println(margin + " [O] " + thisOrdinal + " : " + versionList.toString()); } - Iterator<String> sItr = domainMap.keySet().iterator(); - while (sItr.hasNext()) + for (String thisDomainName : domainMap.keySet()) { - String domainKey = sItr.next(); - AmqpVersionSet versionList = domainMap.get(domainKey); - out.println(margin + " [D] " + domainKey + " : " + versionList.toString()); + AmqpVersionSet versionList = domainMap.get(thisDomainName); + out.println(margin + " [D] " + thisDomainName + " : " + versionList.toString()); } } + + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + if (!versionSet.equals(globalVersionSet)) + return false; + if (!domainMap.isVersionConsistent(globalVersionSet)) + return false; + if (!ordinalMap.isVersionConsistent(globalVersionSet)) + return false; + return true; + } } diff --git a/gentools/org/apache/qpid/gentools/AmqpFieldMap.java b/gentools/src/org/apache/qpid/gentools/AmqpFieldMap.java index 8e7421b45a..5053fba2aa 100644 --- a/gentools/org/apache/qpid/gentools/AmqpFieldMap.java +++ b/gentools/src/org/apache/qpid/gentools/AmqpFieldMap.java @@ -1,18 +1,21 @@ /* * - * 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. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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; @@ -24,24 +27,78 @@ import java.util.Iterator; import java.util.TreeMap; @SuppressWarnings("serial") -public class AmqpFieldMap extends TreeMap<String, AmqpField> +public class AmqpFieldMap extends TreeMap<String, AmqpField> implements VersionConsistencyCheck { public AmqpFieldMap getFieldMapForOrdinal(int ordinal) { AmqpFieldMap newMap = new AmqpFieldMap(); - Iterator<String> i = keySet().iterator(); - while (i.hasNext()) + for (String thisFieldName: keySet()) { - String fieldName = i.next(); - AmqpField field = get(fieldName); + AmqpField field = get(thisFieldName); TreeMap<Integer, AmqpVersionSet> ordinalMap = field.ordinalMap; AmqpVersionSet ordinalVersions = ordinalMap.get(ordinal); if (ordinalVersions != null) - newMap.put(fieldName, field); + { + newMap.put(field.name, field); + } } return newMap; } + public AmqpOrdinalFieldMap getMapForVersion(AmqpVersion version, boolean codeTypeFlag, + LanguageConverter converter) + throws AmqpTypeMappingException + { + // TODO: REVIEW THIS! There may be a bug here that affects C++ generation (only with >1 version)... + // If version == null (a common scenario) then the version map is built up on the + // basis of first found item, and ignores other version variations. + // This should probably be disallowed by throwing an NPE, as AmqpOrdinalFieldMap cannot + // represent these possibilities. + // *OR* + // Change the structure of AmqpOrdianlFieldMap to allow for the various combinations that + // will result from version variation - but that is what AmqpFieldMap is... :-$ + AmqpOrdinalFieldMap ordinalFieldMap = new AmqpOrdinalFieldMap(); + for (String thisFieldName: keySet()) + { + AmqpField field = get(thisFieldName); + if (version == null || field.versionSet.contains(version)) + { + // 1. Search for domain name in field domain map with version that matches + String domain = ""; + boolean dFound = false; + for (String thisDomainName : field.domainMap.keySet()) + { + domain = thisDomainName; + AmqpVersionSet versionSet = field.domainMap.get(domain); + if (version == null || versionSet.contains(version)) + { + if (codeTypeFlag) + domain = converter.getGeneratedType(domain, version); + dFound = true; + } + } + + // 2. Search for ordinal in field ordianl map with version that matches + int ordinal = -1; + boolean oFound = false; + for (Integer thisOrdinal : field.ordinalMap.keySet()) + { + ordinal = thisOrdinal; + AmqpVersionSet versionSet = field.ordinalMap.get(ordinal); + if (version == null || versionSet.contains(version)) + oFound = true; + } + + if (dFound && oFound) + { + String[] fieldDomainPair = {field.name, domain}; + ordinalFieldMap.put(ordinal, fieldDomainPair); + } + } + } + return ordinalFieldMap; + } + public boolean isDomainConsistent(Generator generator, AmqpVersionSet versionSet) throws AmqpTypeMappingException { @@ -53,10 +110,9 @@ public class AmqpFieldMap extends TreeMap<String, AmqpField> public int getNumFields(AmqpVersion version) { int fCntr = 0; - Iterator<String> fItr = keySet().iterator(); - while (fItr.hasNext()) + for (String thisFieldName : keySet()) { - AmqpField field = get(fItr.next()); + AmqpField field = get(thisFieldName); if (field.versionSet.contains(version)) fCntr++; } @@ -64,7 +120,7 @@ public class AmqpFieldMap extends TreeMap<String, AmqpField> } public String parseFieldMap(Method commonGenerateMethod, Method mangledGenerateMethod, - int indentSize, int tabSize, Generator codeGenerator) + int indentSize, int tabSize, LanguageConverter converter) throws AmqpTypeMappingException, IllegalAccessException, InvocationTargetException { String indent = Utils.createSpaces(indentSize); @@ -86,19 +142,19 @@ public class AmqpFieldMap extends TreeMap<String, AmqpField> { String fieldName = itr.next(); AmqpField field = get(fieldName); - if (field.isCodeTypeConsistent(codeGenerator)) + if (field.isCodeTypeConsistent(converter)) { // All versions identical - Common declaration String domainName = field.domainMap.firstKey(); AmqpVersionSet versionSet = field.domainMap.get(domainName); - String codeType = codeGenerator.getGeneratedType(domainName, versionSet.first()); + String codeType = converter.getGeneratedType(domainName, versionSet.first()); if (commonGenerateMethod != null) - sb.append(commonGenerateMethod.invoke(codeGenerator, codeType, field, versionSet, + sb.append(commonGenerateMethod.invoke(converter, codeType, field, versionSet, indentSize, tabSize, itr.hasNext())); } else if (mangledGenerateMethod != null) // Version-mangled { - sb.append(mangledGenerateMethod.invoke(codeGenerator, field, indentSize, tabSize, + sb.append(mangledGenerateMethod.invoke(converter, field, indentSize, tabSize, itr.hasNext())); } } @@ -107,7 +163,6 @@ public class AmqpFieldMap extends TreeMap<String, AmqpField> 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); @@ -268,4 +323,15 @@ public class AmqpFieldMap extends TreeMap<String, AmqpField> indentSize, tabSize)); return sb.toString(); } + + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + for (String thisFieldName : keySet()) + { + AmqpField field = get(thisFieldName); + if (!field.isVersionConsistent(globalVersionSet)) + return false; + } + return true; + } } diff --git a/gentools/src/org/apache/qpid/gentools/AmqpFlagMap.java b/gentools/src/org/apache/qpid/gentools/AmqpFlagMap.java new file mode 100644 index 0000000000..88f337cbe3 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpFlagMap.java @@ -0,0 +1,47 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 AmqpFlagMap extends TreeMap<Boolean, AmqpVersionSet> implements VersionConsistencyCheck +{ + public boolean isSet() + { + return containsKey(true); + } + + public String toString() + { + AmqpVersionSet versionSet = get(true); + if (versionSet != null) + return versionSet.toString(); + return ""; + } + + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + if (size() != 1) + return false; + return get(firstKey()).equals(globalVersionSet); + } +} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpMethod.java b/gentools/src/org/apache/qpid/gentools/AmqpMethod.java new file mode 100644 index 0000000000..126949b44f --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpMethod.java @@ -0,0 +1,174 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class AmqpMethod implements Printable, NodeAware, VersionConsistencyCheck +{ + public LanguageConverter converter; + public AmqpVersionSet versionSet; + public AmqpFieldMap fieldMap; + public String name; + public AmqpOrdinalVersionMap indexMap; + public AmqpFlagMap clientMethodFlagMap; // Method called on client (<chassis name="server"> in XML) + public AmqpFlagMap serverMethodFlagMap; // Method called on server (<chassis name="client"> in XML) + + public AmqpMethod(String name, LanguageConverter converter) + { + this.name = name; + this.converter = converter; + versionSet = new AmqpVersionSet(); + fieldMap = new AmqpFieldMap(); + indexMap = new AmqpOrdinalVersionMap(); + clientMethodFlagMap = new AmqpFlagMap(); + serverMethodFlagMap = new AmqpFlagMap(); + } + + public void addFromNode(Node methodNode, int ordinal, AmqpVersion version) + throws AmqpParseException, AmqpTypeMappingException + { + boolean serverChassisFlag = false; + boolean clientChassisFlag = false; + 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); + } + if (child.getNodeName().compareTo(Utils.ELEMENT_CHASSIS) == 0) + { + String chassisName = Utils.getNamedAttribute(child, Utils.ATTRIBUTE_NAME); + if (chassisName.compareTo("server") == 0) + serverChassisFlag = true; + else if (chassisName.compareTo("client") == 0) + clientChassisFlag = true; + } + } + processChassisFlags(serverChassisFlag, clientChassisFlag, 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 + " {" + (serverMethodFlagMap.isSet() ? "S " + + serverMethodFlagMap + (clientMethodFlagMap.isSet() ? ", " : "") : "") + + (clientMethodFlagMap.isSet() ? "C " + clientMethodFlagMap : "") + "}" + ": " + versionSet); + + for (Integer thisIndex : indexMap.keySet()) + { + AmqpVersionSet indexVersionSet = indexMap.get(thisIndex); + out.println(margin + tab + "[I] " + thisIndex + indexVersionSet); + } + + for (String thisFieldName : fieldMap.keySet()) + { + AmqpField thisField = fieldMap.get(thisFieldName); + thisField.print(out, marginSize + tabSize, tabSize); + } + } + + protected void processChassisFlags(boolean serverFlag, boolean clientFlag, AmqpVersion version) + { + AmqpVersionSet versionSet = serverMethodFlagMap.get(serverFlag); + if (versionSet != null) + versionSet.add(version); + else + { + versionSet = new AmqpVersionSet(); + versionSet.add(version); + serverMethodFlagMap.put(serverFlag, versionSet); + } + + versionSet = clientMethodFlagMap.get(clientFlag); + if (versionSet != null) + versionSet.add(version); + else + { + versionSet = new AmqpVersionSet(); + versionSet.add(version); + clientMethodFlagMap.put(clientFlag, versionSet); + } + } + + public AmqpOverloadedParameterMap getOverloadedParameterLists(AmqpVersionSet globalVersionSet, + Generator generator) + throws AmqpTypeMappingException + { + AmqpOverloadedParameterMap parameterVersionMap = new AmqpOverloadedParameterMap(); + for (AmqpVersion thisVersion : globalVersionSet) + { + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(thisVersion, true, generator); + AmqpVersionSet methodVersionSet = parameterVersionMap.get(ordinalFieldMap); + if (methodVersionSet == null) + { + methodVersionSet = new AmqpVersionSet(); + methodVersionSet.add(thisVersion); + parameterVersionMap.put(ordinalFieldMap, methodVersionSet); + } + else + { + methodVersionSet.add(thisVersion); + } + } + return parameterVersionMap; + } + + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + if (!versionSet.equals(globalVersionSet)) + return false; + if (!clientMethodFlagMap.isVersionConsistent(globalVersionSet)) + return false; + if (!serverMethodFlagMap.isVersionConsistent(globalVersionSet)) + return false; + if (!indexMap.isVersionConsistent(globalVersionSet)) + return false; + if (!fieldMap.isVersionConsistent(globalVersionSet)) + return false; + return true; + } +} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpMethodMap.java b/gentools/src/org/apache/qpid/gentools/AmqpMethodMap.java new file mode 100644 index 0000000000..25a41df131 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpMethodMap.java @@ -0,0 +1,29 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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/src/org/apache/qpid/gentools/AmqpModel.java index f379674f49..caf8bbcdaf 100644 --- a/gentools/org/apache/qpid/gentools/AmqpModel.java +++ b/gentools/src/org/apache/qpid/gentools/AmqpModel.java @@ -1,24 +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. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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; @@ -63,11 +65,9 @@ public class AmqpModel implements Printable, NodeAware "[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()) + for (String thisClassName : classMap.keySet()) { - String className = i.next(); - AmqpClass thisClass = classMap.get(className); + AmqpClass thisClass = classMap.get(thisClassName); thisClass.print(out, marginSize + tabSize, tabSize); } } diff --git a/gentools/src/org/apache/qpid/gentools/AmqpOrdinalFieldMap.java b/gentools/src/org/apache/qpid/gentools/AmqpOrdinalFieldMap.java new file mode 100644 index 0000000000..34d3b7ca5f --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpOrdinalFieldMap.java @@ -0,0 +1,89 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.Iterator; +import java.util.Set; +import java.util.TreeMap; + +@SuppressWarnings("serial") +public class AmqpOrdinalFieldMap extends TreeMap<Integer, String[]> implements Comparable +{ + protected static final int FIELD_DOMAIN = 1; + protected boolean codeTypeFlag = false; + + public int compareTo(Object obj) + { + AmqpOrdinalFieldMap o = (AmqpOrdinalFieldMap)obj; + Set<Integer> thisKeySet = keySet(); + Set<Integer> oKeySet = o.keySet(); + if (!thisKeySet.equals(oKeySet)) // Not equal, but why? + { + // Size difference + int sizeDiff = thisKeySet.size() - oKeySet.size(); // -ve if this < other + if (sizeDiff != 0) + return sizeDiff; + // Conetent difference + Iterator<Integer> itr = thisKeySet.iterator(); + Iterator<Integer> oItr = oKeySet.iterator(); + while (itr.hasNext() && oItr.hasNext()) + { + int diff = itr.next() - oItr.next(); // -ve if this < other + if (diff != 0) + return diff; + } + // We should never get here... + System.err.println("AmqpOrdinalFieldMap.compareTo(): " + + "WARNING - unable to find cause of keySet difference."); + } + // Keys are equal, now check the String[]s + Iterator<Integer> itr = thisKeySet.iterator(); + Iterator<Integer> oItr = oKeySet.iterator(); + while (itr.hasNext() && oItr.hasNext()) + { + String[] thisPair = get(itr.next()); + String[] oPair = o.get(oItr.next()); + // Size difference + int sizeDiff = thisPair.length - oPair.length; // -ve if this < other + if (sizeDiff != 0) + return sizeDiff; + // Conetent difference + for (int i=0; i<thisPair.length; i++) + { + int diff = thisPair[i].compareTo(oPair[i]); + if (diff != 0) + return diff; + } + } + return 0; + } + + public String toString() + { + StringBuffer sb = new StringBuffer(); + for (Integer thisOrdinal : keySet()) + { + String[] pair = get(thisOrdinal); + sb.append("[" + thisOrdinal + "] " + pair[0] + " : " + pair[1] + Utils.lineSeparator); + } + return sb.toString(); + } +} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpOrdinalVersionMap.java b/gentools/src/org/apache/qpid/gentools/AmqpOrdinalVersionMap.java new file mode 100644 index 0000000000..3f4a9f39e6 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpOrdinalVersionMap.java @@ -0,0 +1,46 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 AmqpOrdinalVersionMap extends TreeMap<Integer, AmqpVersionSet> implements VersionConsistencyCheck +{ + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + if (size() != 1) + return false; + return get(firstKey()).equals(globalVersionSet); + } + + public int getOrdinal(AmqpVersion version) + throws AmqpTypeMappingException + { + for (Integer thisOrdinal : keySet()) + { + AmqpVersionSet versionSet = get(thisOrdinal); + if (versionSet.contains(version)) + return thisOrdinal; + } + throw new AmqpTypeMappingException("Unable to locate version " + version + " in ordianl version map."); + } +} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpOverloadedParameterMap.java b/gentools/src/org/apache/qpid/gentools/AmqpOverloadedParameterMap.java new file mode 100644 index 0000000000..10978d0e4a --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpOverloadedParameterMap.java @@ -0,0 +1,29 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 AmqpOverloadedParameterMap extends TreeMap<AmqpOrdinalFieldMap, AmqpVersionSet> +{ + +} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpParseException.java b/gentools/src/org/apache/qpid/gentools/AmqpParseException.java new file mode 100644 index 0000000000..4d9f495390 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpParseException.java @@ -0,0 +1,30 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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/src/org/apache/qpid/gentools/AmqpTemplateException.java b/gentools/src/org/apache/qpid/gentools/AmqpTemplateException.java new file mode 100644 index 0000000000..b1e6f3d712 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpTemplateException.java @@ -0,0 +1,30 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 AmqpTemplateException extends Exception +{ + public AmqpTemplateException(String msg) + { + super(msg); + } +} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpTypeMappingException.java b/gentools/src/org/apache/qpid/gentools/AmqpTypeMappingException.java new file mode 100644 index 0000000000..1053543fdd --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpTypeMappingException.java @@ -0,0 +1,30 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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/src/org/apache/qpid/gentools/AmqpVersion.java b/gentools/src/org/apache/qpid/gentools/AmqpVersion.java new file mode 100644 index 0000000000..0c0c5a5cbf --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpVersion.java @@ -0,0 +1,62 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 namespace() + { + return "ver_" + major + "_" + minor; + } + + public String toString() + { + return major + "-" + minor; + } +} diff --git a/gentools/src/org/apache/qpid/gentools/AmqpVersionSet.java b/gentools/src/org/apache/qpid/gentools/AmqpVersionSet.java new file mode 100644 index 0000000000..06b10cfda6 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/AmqpVersionSet.java @@ -0,0 +1,62 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.TreeSet; + +@SuppressWarnings("serial") +public class AmqpVersionSet extends TreeSet<AmqpVersion> implements Printable, Comparable<AmqpVersionSet> +{ + public AmqpVersionSet() + { + } + + public AmqpVersionSet(AmqpVersion version) + { + add(version); + } + + public void print(PrintStream out, int marginSize, int tabSize) + { + out.print(Utils.createSpaces(marginSize) + "Version Set: " + toString() + Utils.lineSeparator); + } + + public int compareTo(AmqpVersionSet other) + { + int res = size() - other.size(); + if (res != 0) + return res; + Iterator<AmqpVersion> vItr = iterator(); + Iterator<AmqpVersion> oItr = other.iterator(); + while (vItr.hasNext() && oItr.hasNext()) + { + AmqpVersion version = vItr.next(); + AmqpVersion oVersion = oItr.next(); + res = version.compareTo(oVersion); + if (res != 0) + return res; + } + return 0; + } +} diff --git a/gentools/src/org/apache/qpid/gentools/CppGenerator.java b/gentools/src/org/apache/qpid/gentools/CppGenerator.java new file mode 100644 index 0000000000..f1e7063800 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/CppGenerator.java @@ -0,0 +1,1628 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 java.util.ArrayList; +import java.util.Iterator; +import java.util.TreeMap; + +public class CppGenerator extends Generator +{ + protected static final String versionNamespaceStartToken = "${version_namespace_start}"; + protected static final String versionNamespaceEndToken = "${version_namespace_end}"; + + // TODO: Move this to parent class + protected static final int FIELD_NAME = 0; + protected static final int FIELD_CODE_TYPE = 1; + + /** + * A complete list of C++ reserved words. The names of varous XML elements within the AMQP + * specification file are used for C++ identifier names in the generated code. Each proposed + * name is checked against this list and is modified (by adding an '_' to the end of the + * name - see function parseForReservedWords()) if found to be present. + */ + protected static final String[] cppReservedWords = {"and", "and_eq", "asm", "auto", "bitand", + "bitor", "bool", "break", "case", "catch", "char", "class", "compl", "const", "const_cast", + "continue", "default", "delete", "do", "DomainInfo", "double", "dynamic_cast", "else", + "enum", "explicit", "extern", "false", "float", "for", "friend", "goto", "if", "inline", + "int", "long", "mutable", "namespace", "new", "not", "not_eq", "operator", "or", "or_eq", + "private", "protected", "public", "register", "reinterpret_cast", "return", "short", + "signed", "sizeof", "static", "static_cast", "struct", "switch", "template", "this", + "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned", "using", + "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq"}; + + /** + * Although not reserved words, the following list of variable names that may cause compile + * problems within a C++ environment because they clash with common #includes. The names of + * varous XML elements within the AMQP specification file are used for C++ identifier names + * in the generated code. Each proposed name is checked against this list and is modified + * (by adding an '_' to the end of the name - see function parseForReservedWords()) if found + * to be present. This list is best added to on an as-needed basis. + */ + protected static final String[] cppCommonDefines = {"string"}; + + // TODO: Move this to the Generator superclass? + protected boolean quietFlag; // Supress warning messages to the console + + 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>(); + + public CppGenerator(AmqpVersionSet versionList) + { + super(versionList); + quietFlag = true; + // 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 (any type). + // The char '~' will be replaced by the compacted bit array size (type bit only). + typeMap.put("bit", new DomainInfo( + "bool", // type + "~", // size + "", // encodeExpression + "")); // decodeExpression + typeMap.put("content", new DomainInfo( + "Content", // type + "#.size()", // size + "buffer.putContent(#)", // encodeExpression + "buffer.getContent(#)")); // decodeExpression + typeMap.put("long", new DomainInfo( + "u_int32_t", // type + "4", // size + "buffer.putLong(#)", // encodeExpression + "# = buffer.getLong()")); // decodeExpression + typeMap.put("longlong", new DomainInfo( + "u_int64_t", // type + "8", // size + "buffer.putLongLong(#)", // encodeExpression + "# = buffer.getLongLong()")); // decodeExpression + typeMap.put("longstr", new DomainInfo( + "string", // type + "4 + #.length()", // size + "buffer.putLongString(#)", // encodeExpression + "buffer.getLongString(#)")); // decodeExpression + typeMap.put("octet", new DomainInfo( + "u_int8_t", // type + "1", // size + "buffer.putOctet(#)", // encodeExpression + "# = buffer.getOctet()")); // decodeExpression + typeMap.put("short", new DomainInfo( + "u_int16_t", // type + "2", // size + "buffer.putShort(#)", // encodeExpression + "# = buffer.getShort()")); // decodeExpression + typeMap.put("shortstr", new DomainInfo( + "string", // type + "1 + #.length()", // size + "buffer.putShortString(#)", // encodeExpression + "buffer.getShortString(#)")); // decodeExpression + typeMap.put("table", new DomainInfo( + "FieldTable", // type + "#.size()", // size + "buffer.putFieldTable(#)", // encodeExpression + "buffer.getFieldTable(#)")); // decodeExpression + typeMap.put("timestamp", new DomainInfo( + "u_int64_t", // type + "8", // size + "buffer.putLongLong(#)", // encodeExpression + "buffer.getLongLong(#)")); // decodeExpression + } + + public boolean isQuietFlag() + { + return quietFlag; + } + + public void setQuietFlag(boolean quietFlag) + { + this.quietFlag = quietFlag; + } + + // === 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 + { + if (version == null) + version = globalVersionSet.first(); + return globalDomainMap.getDomainType(domainName, version); + } + + public String getGeneratedType(String domainName, AmqpVersion version) + throws AmqpTypeMappingException + { + String domainType = getDomainType(domainName, version); + if (domainType == null) + { + throw new AmqpTypeMappingException("Domain type \"" + domainName + + "\" not found in C++ typemap."); + } + DomainInfo info = typeMap.get(domainType); + if (info == null) + { + throw new AmqpTypeMappingException("Unknown domain: \"" + domainType + "\""); + } + return info.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 void processTemplateA(String[] template) + throws IOException, AmqpTemplateException, AmqpTypeMappingException, + IllegalAccessException, InvocationTargetException + { + processTemplateD(template, null, null, null); + } + + @Override + protected void processTemplateB(String[] template, AmqpClass thisClass) + throws IOException, AmqpTemplateException, AmqpTypeMappingException, + IllegalAccessException, InvocationTargetException + { + processTemplateD(template, thisClass, null, null); + } + + @Override + protected void processTemplateC(String[] template, AmqpClass thisClass, + AmqpMethod method) + throws IOException, AmqpTemplateException, AmqpTypeMappingException, + IllegalAccessException, InvocationTargetException + { + StringBuffer sb = new StringBuffer(template[templateStringIndex]); + String filename = prepareFilename(getTemplateFileName(sb), thisClass, method, null); + boolean templateProcessedFlag = false; + + // If method is not version consistent, create a namespace for each version + // i.e. copy the bit between the versionNamespaceStartToken and versionNamespaceEndToken + // once for each namespace. + if (method != null) + { + if (!method.isVersionConsistent(globalVersionSet)) + { + int namespaceStartIndex = sb.indexOf(versionNamespaceStartToken); + int namespaceEndIndex = sb.indexOf(versionNamespaceEndToken) + + versionNamespaceEndToken.length(); + if (namespaceStartIndex >= 0 && namespaceEndIndex >= 0 && + namespaceStartIndex <= namespaceEndIndex) + { + String namespaceSpan = sb.substring(namespaceStartIndex, namespaceEndIndex) + cr; + sb.delete(namespaceStartIndex, namespaceEndIndex); + for (AmqpVersion v : method.versionSet) + { + StringBuffer nssb = new StringBuffer(namespaceSpan); + processTemplate(nssb, thisClass, method, null, template[templateFileNameIndex], v); + sb.insert(namespaceStartIndex, nssb); + } + // Process all tokens *not* within the namespace span prior to inserting namespaces + processTemplate(sb, thisClass, method, null, template[templateFileNameIndex], null); + } + templateProcessedFlag = true; + } + } + // Remove any remaining namespace tags + int nsTokenIndex = sb.indexOf(versionNamespaceStartToken); + while (nsTokenIndex > 0) + { + sb.delete(nsTokenIndex, nsTokenIndex + versionNamespaceStartToken.length()); + nsTokenIndex = sb.indexOf(versionNamespaceStartToken); + } + nsTokenIndex = sb.indexOf(versionNamespaceEndToken); + while (nsTokenIndex > 0) + { + sb.delete(nsTokenIndex, nsTokenIndex + versionNamespaceEndToken.length()); + nsTokenIndex = sb.indexOf(versionNamespaceEndToken); + } + + if (!templateProcessedFlag) + { + processTemplate(sb, thisClass, method, null, template[templateFileNameIndex], null); + } + writeTargetFile(sb, new File(genDir + Utils.fileSeparator + filename)); + generatedFileCounter ++; + } + + @Override + protected void processTemplateD(String[] template, AmqpClass thisClass, AmqpMethod method, + AmqpField field) + throws IOException, AmqpTemplateException, AmqpTypeMappingException, IllegalAccessException, + InvocationTargetException + { + StringBuffer sb = new StringBuffer(template[templateStringIndex]); + String filename = prepareFilename(getTemplateFileName(sb), thisClass, method, field); + processTemplate(sb, thisClass, method, field, template[templateFileNameIndex], null); + writeTargetFile(sb, new File(genDir + Utils.fileSeparator + filename)); + generatedFileCounter ++; + } + + protected void processTemplate(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, + AmqpField field, String templateFileName, AmqpVersion version) + throws InvocationTargetException, IllegalAccessException, AmqpTypeMappingException + { + try { processAllLists(sb, thisClass, method, version); } + catch (AmqpTemplateException e) + { + System.out.println("ERROR: " + templateFileName + ": " + e.getMessage()); + } + try { processAllTokens(sb, thisClass, method, field, version); } + catch (AmqpTemplateException e) + { + System.out.println("ERROR: " + templateFileName + ": " + e.getMessage()); + } + } + + @Override + protected String processToken(String token, AmqpClass thisClass, AmqpMethod method, AmqpField field, + AmqpVersion version) + throws AmqpTemplateException, AmqpTypeMappingException + { + 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) + { + if (version == null) + return String.valueOf(thisClass.indexMap.firstKey()); + return getIndex(thisClass.indexMap, version); + } + if (token.compareTo("${METHOD}") == 0 && method != null) + return method.name; + if (token.compareTo("${METHOD_ID_INIT}") == 0 && method != null) + { + if (version == null) + return String.valueOf(method.indexMap.firstKey()); + return getIndex(method.indexMap, version); + } + if (token.compareTo("${FIELD}") == 0 && field != null) + return field.name; + if (token.compareTo(versionNamespaceStartToken) == 0 && version != null) + return "namespace " + version.namespace() + cr + "{"; + if (token.compareTo(versionNamespaceEndToken) == 0 && version != null) + return "} // namespace " + version.namespace(); + if (token.compareTo("${mb_constructor_with_initializers}") == 0) + return generateConstructor(thisClass, method, version, 4, 4); + if (token.compareTo("${mb_server_operation_invoke}") == 0) + return generateServerOperationsInvoke(thisClass, method, version, 4, 4); + if (token.compareTo("${mb_buffer_param}") == 0) + return method.fieldMap.size() > 0 ? " buffer" : ""; + if (token.compareTo("${hv_latest_major}") == 0) + return String.valueOf(globalVersionSet.last().getMajor()); + if (token.compareTo("${hv_latest_minor}") == 0) + return String.valueOf(globalVersionSet.last().getMinor()); + + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + + @Override + protected void processClassList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpModel model) + throws AmqpTemplateException, AmqpTypeMappingException + { + String codeSnippet; + int lend = sb.indexOf(cr, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokxStart = tline.indexOf('$'); + String token = tline.substring(tokxStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + // ClientOperations.h + if (token.compareTo("${coh_method_handler_get_method}") == 0) + { + codeSnippet = generateOpsMethodHandlerGetMethods(model, false, 4); + } + else if (token.compareTo("${coh_inner_class}") == 0) + { + codeSnippet = generateOpsInnerClasses(model, false, 4, 4); + } + + // ServerOperations.h + else if (token.compareTo("${soh_method_handler_get_method}") == 0) + { + codeSnippet = generateOpsMethodHandlerGetMethods(model, true, 4); + } + else if (token.compareTo("${soh_inner_class}") == 0) + { + codeSnippet = generateOpsInnerClasses(model, true, 4, 4); + } + + // ClientProxy.h/cpp + else if (token.compareTo("${cph_inner_class_instance}") == 0) + { + codeSnippet = generateProxyInnerClassInstances(model, false, 4); + } + else if (token.compareTo("${cph_inner_class_get_method}") == 0) + { + codeSnippet = generateProxyInnerClassGetMethodDecls(model, false, 4); + } + else if (token.compareTo("${cph_inner_class_defn}") == 0) + { + codeSnippet = generateProxyInnerClassDefinitions(model, false, 4, 4); + } + else if (token.compareTo("${cpc_constructor_initializer}") == 0) + { + codeSnippet = generateProxyConstructorInitializers(model, false, 4); + } + else if (token.compareTo("${cpc_inner_class_get_method}") == 0) + { + codeSnippet = generateProxyInnerClassGetMethodImpls(model, false, 0, 4); + } + else if (token.compareTo("${cpc_inner_class_impl}") == 0) + { + codeSnippet = generateProxyInnerClassImpl(model, false, 0, 4); + } + else if (token.compareTo("${cph_handler_pointer_defn}") == 0) + { + codeSnippet = generateHandlerPointerDefinitions(model, false, 4); + } + else if (token.compareTo("${cph_handler_pointer_get_method}") == 0) + { + codeSnippet = generateHandlerPointerGetMethods(model, false, 4); + } + + // SerrverProxy.h/cpp + else if (token.compareTo("${sph_inner_class_instance}") == 0) + { + codeSnippet = generateProxyInnerClassInstances(model, true, 4); + } + else if (token.compareTo("${sph_inner_class_get_method}") == 0) + { + codeSnippet = generateProxyInnerClassGetMethodDecls(model, true, 4); + } + else if (token.compareTo("${sph_inner_class_defn}") == 0) + { + codeSnippet = generateProxyInnerClassDefinitions(model, true, 4, 4); + } + else if (token.compareTo("${spc_constructor_initializer}") == 0) + { + codeSnippet = generateProxyConstructorInitializers(model, true, 4); + } + else if (token.compareTo("${spc_inner_class_get_method}") == 0) + { + codeSnippet = generateProxyInnerClassGetMethodImpls(model, true, 0, 4); + } + else if (token.compareTo("${spc_inner_class_impl}") == 0) + { + codeSnippet = generateProxyInnerClassImpl(model, true, 0, 4); + } + else if (token.compareTo("${sph_handler_pointer_defn}") == 0) + { + codeSnippet = generateHandlerPointerDefinitions(model, true, 4); + } + else if (token.compareTo("${sph_handler_pointer_get_method}") == 0) + { + codeSnippet = generateHandlerPointerGetMethods(model, true, 4); + } + + // amqp_methods.h/cpp + else if (token.compareTo("${mh_method_body_class_indlude}") == 0) + { + codeSnippet = generateMethodBodyIncludeList(model, 0); + } + else if (token.compareTo("${mh_method_body_class_instance}") == 0) + { + codeSnippet = generateMethodBodyInstances(model, 0); + } + else if (token.compareTo("${mc_create_method_body_map_entry}") == 0) + { + codeSnippet = generateMethodBodyMapEntry(model, 4); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token \"" + token + "\" unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } + + @Override + protected void processMethodList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpClass thisClass) + throws AmqpTemplateException, AmqpTypeMappingException + { + String codeSnippet; + int lend = sb.indexOf(cr, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokxStart = tline.indexOf('$'); + String token = tline.substring(tokxStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + if (token.compareTo("${cpc_method_body_include}") == 0) + { + codeSnippet = generateMethodBodyIncludes(thisClass, 0); + } + else if (token.compareTo("${spc_method_body_include}") == 0) + { + codeSnippet = generateMethodBodyIncludes(thisClass, 0); + } + else if (token.compareTo("${mc_method_body_include}") == 0) + { + codeSnippet = generateMethodBodyIncludes(thisClass, 0); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } + + @Override + protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpFieldMap fieldMap, AmqpVersion version) + 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); + + if (token.compareTo("${mb_field_declaration}") == 0) + { + codeSnippet = generateFieldDeclarations(fieldMap, version, 4); + } + else if (token.compareTo("${mb_field_get_method}") == 0) + { + codeSnippet = generateFieldGetMethods(fieldMap, version, 4); + } + else if (token.compareTo("${mb_field_print}") == 0) + { + codeSnippet = generatePrintMethodContents(fieldMap, version, 8); + } + else if (token.compareTo("${mb_body_size}") == 0) + { + codeSnippet = generateBodySizeMethodContents(fieldMap, version, 8); + } + else if (token.compareTo("${mb_encode}") == 0) + { + codeSnippet = generateEncodeMethodContents(fieldMap, version, 8); + } + else if (token.compareTo("${mb_decode}") == 0) + { + codeSnippet = generateDecodeMethodContents(fieldMap, version, 8); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } + + @Override + protected void processConstantList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpConstantSet constantSet) + throws AmqpTemplateException, AmqpTypeMappingException + { + String codeSnippet; + int lend = sb.indexOf(cr, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokxStart = tline.indexOf('$'); + String token = tline.substring(tokxStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + if (token.compareTo("${ch_get_value_method}") == 0) + { + codeSnippet = generateConstantGetMethods(constantSet, 4, 4); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } + + // === Protected and private helper functions unique to C++ implementation === + + // Methods for generation of code snippets for AMQP_Constants.h file + + protected String generateConstantGetMethods(AmqpConstantSet constantSet, + int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + for (AmqpConstant thisConstant : constantSet) + { + if (thisConstant.isVersionConsistent(globalVersionSet)) + { + // return a constant + String value = thisConstant.firstKey(); + sb.append(indent + "static const char* " + thisConstant.name + "() { return \"" + + thisConstant.firstKey() + "\"; }" + cr); + if (Utils.containsOnlyDigits(value)) + { + sb.append(indent + "static int " + thisConstant.name + "AsInt() { return " + + thisConstant.firstKey() + "; }" + cr); + } + if (Utils.containsOnlyDigitsAndDecimal(value)) + { + sb.append(indent + "static double " + thisConstant.name + "AsDouble() { return (double)" + + thisConstant.firstKey() + "; }" + cr); + } + sb.append(cr); + } + else + { + // Return version-specific constant + sb.append(generateVersionDependentGet(thisConstant, "const char*", "", "\"", "\"", indentSize, tabSize)); + sb.append(generateVersionDependentGet(thisConstant, "int", "AsInt", "", "", indentSize, tabSize)); + sb.append(generateVersionDependentGet(thisConstant, "double", "AsDouble", "(double)", "", indentSize, tabSize)); + sb.append(cr); + } + } + return sb.toString(); + } + + protected String generateVersionDependentGet(AmqpConstant constant, String methodReturnType, + String methodNameSuffix, String returnPrefix, String returnPostfix, int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + sb.append(indent + methodReturnType + " " + constant.name + methodNameSuffix + + "() const" + cr); + sb.append(indent + "{" + cr); + boolean first = true; + for (String thisValue : constant.keySet()) + { + AmqpVersionSet versionSet = constant.get(thisValue); + sb.append(indent + tab + (first ? "" : "else ") + "if (" + generateVersionCheck(versionSet) + + ")" + cr); + sb.append(indent + tab + "{" + cr); + if (methodReturnType.compareTo("int") == 0 && !Utils.containsOnlyDigits(thisValue)) + { + sb.append(generateConstantDeclarationException(constant.name, methodReturnType, + indentSize + (2*tabSize), tabSize)); + } + else if (methodReturnType.compareTo("double") == 0 && !Utils.containsOnlyDigitsAndDecimal(thisValue)) + { + sb.append(generateConstantDeclarationException(constant.name, methodReturnType, + indentSize + (2*tabSize), tabSize)); + } + else + { + sb.append(indent + tab + tab + "return " + returnPrefix + thisValue + returnPostfix + ";" + cr); + } + sb.append(indent + tab + "}" + cr); + first = false; + } + sb.append(indent + tab + "else" + cr); + sb.append(indent + tab + "{" + cr); + sb.append(indent + tab + tab + "std::stringstream ss;" + cr); + sb.append(indent + tab + tab + "ss << \"Constant \\\"" + constant.name + + "\\\" is undefined for AMQP version \" <<" + cr); + sb.append(indent + tab + tab + tab + "version.toString() << \".\";" + cr); + sb.append(indent + tab + tab + "throw ProtocolVersionException(ss.str());" + cr); + sb.append(indent + tab + "}" + cr); + sb.append(indent + "}" + cr); + return sb.toString(); + } + + protected String generateConstantDeclarationException(String name, String methodReturnType, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + sb.append(indent + "std::stringstream ss;" + cr); + sb.append(indent + "ss << \"Constant \\\"" + name + "\\\" cannot be converted to type " + + methodReturnType + " for AMQP version \" <<" + cr); + sb.append(indent + tab + "version.toString() << \".\";" + cr); + sb.append(indent + "throw ProtocolVersionException(ss.str());" + cr); + return sb.toString(); + } + + // Methods used for generation of code snippets for Server/ClientOperations class generation + + protected String generateOpsMethodHandlerGetMethods(AmqpModel model, boolean serverFlag, int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + for (String thisClassName : model.classMap.keySet()) + { + AmqpClass thisClass = model.classMap.get(thisClassName); + // Only generate for this class if there is at least one method of the + // required chassis (server/client flag). + boolean chassisFoundFlag = false; + for (String thisMethodName : thisClass.methodMap.keySet()) + { + AmqpMethod method = thisClass.methodMap.get(thisMethodName); + boolean clientChassisFlag = method.clientMethodFlagMap.isSet(); + boolean serverChassisFlag = method.serverMethodFlagMap.isSet(); + if ((serverFlag && serverChassisFlag) || (!serverFlag && clientChassisFlag)) + chassisFoundFlag = true; + } + if (chassisFoundFlag) + { + sb.append(indent + "virtual AMQP_" + (serverFlag ? "Server" : "Client") + "Operations::" + + thisClass.name + "Handler* get" + thisClass.name + "Handler() = 0;" + cr); + } + } + return sb.toString(); + } + + protected String generateOpsInnerClasses(AmqpModel model, boolean serverFlag, int indentSize, int tabSize) + throws AmqpTypeMappingException + { + + String proxyClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + boolean first = true; + for (String thisClassName : model.classMap.keySet()) + { + AmqpClass thisClass = model.classMap.get(thisClassName); + String handlerClassName = thisClass.name + "Handler"; + if (!first) + sb.append(cr); + sb.append(indent + "// ==================== class " + handlerClassName + + " ====================" + cr); + sb.append(indent + "class " + handlerClassName); + if (thisClass.versionSet.size() != globalVersionSet.size()) + sb.append(" // AMQP Version(s) " + thisClass.versionSet + cr); + else + sb.append(cr); + sb.append(indent + "{" + cr); + sb.append(indent + "private:" + cr); + sb.append(indent + tab + proxyClassName+ "* parent;" + cr); + sb.append(cr); + sb.append(indent + tab + "// Constructors and destructors" + cr); + sb.append(cr); + sb.append(indent + "protected:" + cr); + sb.append(indent + tab + handlerClassName + "() {}" + cr); + sb.append(indent + "public:" + cr); + sb.append(indent + tab + handlerClassName + + "(" + proxyClassName + "* _parent) {parent = _parent;}" + cr); + sb.append(indent + tab + "virtual ~" + handlerClassName + "() {}" + cr); + sb.append(cr); + sb.append(indent + tab + "// Protocol methods" + cr); + sb.append(cr); + sb.append(generateInnerClassMethods(thisClass, serverFlag, true, indentSize + tabSize, tabSize)); + sb.append(indent + "}; // class " + handlerClassName + cr); + first = false; + } + return sb.toString(); + } + + protected String generateInnerClassMethods(AmqpClass thisClass, boolean serverFlag, + boolean abstractMethodFlag, int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + (abstractMethodFlag ? "Operations" : "Proxy"); + boolean first = true; + for (String thisMethodName : thisClass.methodMap.keySet()) + { + AmqpMethod method = thisClass.methodMap.get(thisMethodName); + boolean clientChassisFlag = method.clientMethodFlagMap.isSet(); + boolean serverChassisFlag = method.serverMethodFlagMap.isSet(); + if ((serverFlag && serverChassisFlag) || (!serverFlag && clientChassisFlag)) + { + String methodName = parseForReservedWords(method.name, outerClassName + "." + thisClass.name); + AmqpOverloadedParameterMap overloadededParameterMap = + method.getOverloadedParameterLists(thisClass.versionSet, this); + for (AmqpOrdinalFieldMap thisFieldMap : overloadededParameterMap.keySet()) + { + AmqpVersionSet versionSet = overloadededParameterMap.get(thisFieldMap); + if (!first) + sb.append(cr); + sb.append(indent + "virtual void " + methodName + "( u_int16_t channel"); + sb.append(generateMethodParameterList(thisFieldMap, indentSize + (5*tabSize), true, true, true)); + sb.append(" )"); + if (abstractMethodFlag) + sb.append(" = 0"); + sb.append(";"); + if (versionSet.size() != globalVersionSet.size()) + sb.append(" // AMQP Version(s) " + versionSet); + sb.append(cr); + first = false; + } + } + } + return sb.toString(); + } + + // Methods used for generation of code snippets for Server/ClientProxy class generation + + protected String generateHandlerPointerDefinitions(AmqpModel model, boolean serverFlag, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Operations"; + for (String thisClassName : model.classMap.keySet()) + { + AmqpClass thisClass = model.classMap.get(thisClassName); + sb.append(indent + outerClassName + "::" + thisClass.name + "Handler* " + + thisClass.name + "HandlerPtr;" + cr); + } + return sb.toString(); + } + + protected String generateHandlerPointerGetMethods(AmqpModel model, boolean serverFlag, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Operations"; + for (String thisClassName : model.classMap.keySet()) + { + AmqpClass thisClass = model.classMap.get(thisClassName); + sb.append(indent + "virtual inline " + outerClassName + "::" + thisClass.name + "Handler* get" + + thisClass.name + "Handler() { return &" + Utils.firstLower(thisClass.name) + ";}" + cr); + } + return sb.toString(); + } + + protected String generateProxyInnerClassInstances(AmqpModel model, boolean serverFlag, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + for (String thisClassName : model.classMap.keySet()) + { + AmqpClass thisClass = model.classMap.get(thisClassName); + String instanceName = parseForReservedWords(Utils.firstLower(thisClass.name), outerClassName); + String className = parseForReservedWords(thisClass.name, null); + sb.append(indent + className + " " + instanceName + ";"); + if (thisClass.versionSet.size() != globalVersionSet.size()) + sb.append(" // AMQP Version(s) " + thisClass.versionSet + cr); + else + sb.append(cr); + } + return sb.toString(); + } + + protected String generateProxyInnerClassGetMethodDecls(AmqpModel model, boolean serverFlag, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + for (String thisClassName : model.classMap.keySet()) + { + AmqpClass thisClass = model.classMap.get(thisClassName); + String className = parseForReservedWords(thisClass.name, outerClassName); + sb.append(indent + className + "& get" + className + "();"); + if (thisClass.versionSet.size() != globalVersionSet.size()) + sb.append(" // AMQP Version(s) " + thisClass.versionSet + cr); + else + sb.append(cr); + } + return sb.toString(); + } + + protected String generateProxyInnerClassDefinitions(AmqpModel model, boolean serverFlag, + int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String proxyClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + boolean first = true; + for (String thisClassName : model.classMap.keySet()) + { + AmqpClass thisClass = model.classMap.get(thisClassName); + String className = thisClass.name; + String superclassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Operations::" + + thisClass.name + "Handler"; + if (!first) + sb.append(cr); + sb.append(indent + "// ==================== class " + className + + " ====================" + cr); + sb.append(indent + "class " + className + " : virtual public " + superclassName); + if (thisClass.versionSet.size() != globalVersionSet.size()) + sb.append(" // AMQP Version(s) " + thisClass.versionSet + cr); + else + sb.append(cr); + sb.append(indent + "{" + cr); + sb.append(indent + "private:" + cr); + sb.append(indent + tab + "OutputHandler* out;" + cr); + sb.append(indent + tab + proxyClassName + "* parent;" + cr); + sb.append(cr); + sb.append(indent + "public:" + cr); + sb.append(indent + tab + "// Constructors and destructors" + cr); + sb.append(cr); + sb.append(indent + tab + className + "(OutputHandler* out, " + proxyClassName + "* _parent) : " + cr); + sb.append(indent + tab + tab + "out(out) {parent = _parent;}" + cr); + sb.append(indent + tab + "virtual ~" + className + "() {}" + cr); + sb.append(cr); + sb.append(indent + tab + "// Protocol methods" + cr); + sb.append(cr); + sb.append(generateInnerClassMethods(thisClass, serverFlag, false, indentSize + tabSize, tabSize)); + sb.append(indent + "}; // class " + className + cr); + first = false; + } + return sb.toString(); + } + + protected String generateProxyConstructorInitializers(AmqpModel model, boolean serverFlag, + int indentSize) + { + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + String superclassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Operations"; + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(indent + superclassName + "(major, minor)," + cr); + sb.append(indent + "version(major, minor)," + cr); + sb.append(indent + "out(out)"); + Iterator<String> cItr = model.classMap.keySet().iterator(); + while (cItr.hasNext()) + { + AmqpClass thisClass = model.classMap.get(cItr.next()); + String instanceName = parseForReservedWords(Utils.firstLower(thisClass.name), outerClassName); + sb.append("," + cr); + sb.append(indent + instanceName + "(out, this)"); + if (!cItr.hasNext()) + sb.append(cr); + } + return sb.toString(); + } + + protected String generateProxyInnerClassGetMethodImpls(AmqpModel model, boolean serverFlag, + int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + Iterator<String> cItr = model.classMap.keySet().iterator(); + while (cItr.hasNext()) + { + AmqpClass thisClass = model.classMap.get(cItr.next()); + String className = thisClass.name; + String instanceName = parseForReservedWords(Utils.firstLower(thisClass.name), outerClassName); + sb.append(indent + outerClassName + "::" + className + "& " + + outerClassName + "::get" + className + "()" + cr); + sb.append(indent + "{" + cr); + if (thisClass.versionSet.size() != globalVersionSet.size()) + { + sb.append(indent + tab + "if (!" + generateVersionCheck(thisClass.versionSet) + ")" + cr); + sb.append(indent + tab + tab + "throw new ProtocolVersionException();" + cr); + } + sb.append(indent + tab + "return " + instanceName + ";" + cr); + sb.append(indent + "}" + cr); + if (cItr.hasNext()) + sb.append(cr); + } + return sb.toString(); + } + + protected String generateProxyInnerClassImpl(AmqpModel model, boolean serverFlag, + int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + boolean firstClassFlag = true; + for (String thisClassName : model.classMap.keySet()) + { + AmqpClass thisClass = model.classMap.get(thisClassName); + String className = thisClass.name; + if (!firstClassFlag) + sb.append(cr); + sb.append(indent + "// ==================== class " + className + + " ====================" + cr); + sb.append(generateInnerClassMethodImpls(thisClass, serverFlag, indentSize, tabSize)); + firstClassFlag = false; + } + return sb.toString(); + } + + protected String generateInnerClassMethodImpls(AmqpClass thisClass, boolean serverFlag, + int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String outerclassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + boolean first = true; + for (String thisMethodName : thisClass.methodMap.keySet()) + { + AmqpMethod method = thisClass.methodMap.get(thisMethodName); + String methodBodyClassName = thisClass.name + Utils.firstUpper(method.name) + "Body"; + boolean clientChassisFlag = method.clientMethodFlagMap.isSet(); + boolean serverChassisFlag = method.serverMethodFlagMap.isSet(); + boolean versionConsistentFlag = method.isVersionConsistent(globalVersionSet); + if ((serverFlag && serverChassisFlag) || (!serverFlag && clientChassisFlag)) + { + String methodName = parseForReservedWords(method.name, outerclassName + "." + thisClass.name); + AmqpOverloadedParameterMap overloadededParameterMap = + method.getOverloadedParameterLists(thisClass.versionSet, this); + for (AmqpOrdinalFieldMap thisFieldMap : overloadededParameterMap.keySet()) + { + AmqpVersionSet versionSet = overloadededParameterMap.get(thisFieldMap); + if (!first) + sb.append(cr); + sb.append(indent + "void " + outerclassName + "::" + thisClass.name + "::" + + methodName + "( u_int16_t channel"); + sb.append(generateMethodParameterList(thisFieldMap, indentSize + (5*tabSize), true, true, true)); + sb.append(" )"); + if (versionSet.size() != globalVersionSet.size()) + sb.append(" // AMQP Version(s) " + versionSet); + sb.append(cr); + sb.append(indent + "{" + cr); + sb.append(generateMethodBodyCallContext(thisFieldMap, outerclassName, methodBodyClassName, + versionConsistentFlag, versionSet, indentSize + tabSize, tabSize)); + sb.append(indent + "}" + cr); + sb.append(cr); + first = false; + } + } + } + return sb.toString(); + } + + protected String generateMethodBodyCallContext(AmqpOrdinalFieldMap fieldMap, String outerclassName, + String methodBodyClassName, boolean versionConsistentFlag, AmqpVersionSet versionSet, + int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + if (versionConsistentFlag) + { + sb.append(generateMethodBodyCall(fieldMap, methodBodyClassName, null, indentSize, tabSize)); + } + else + { + boolean firstOverloadedMethodFlag = true; + for (AmqpVersion thisVersion : versionSet) + { + sb.append(indent); + if (!firstOverloadedMethodFlag) + sb.append("else "); + sb.append("if (" + generateVersionCheck(thisVersion) + ")" + cr); + sb.append(indent + "{" + cr); + sb.append(generateMethodBodyCall(fieldMap, methodBodyClassName, thisVersion, + indentSize + tabSize, tabSize)); + sb.append(indent + "}" + cr); + firstOverloadedMethodFlag = false; + } + sb.append(indent + "else" + cr); + sb.append(indent + "{" + cr); + sb.append(indent + tab + "std::stringstream ss;" + cr); + sb.append(indent + tab + "ss << \"Call to " + outerclassName + "::" + methodBodyClassName + + "(u_int16_t" + generateMethodParameterList(fieldMap, 0, true, true, false) + ")\"" + cr); + sb.append(indent + tab + tab + "<< \" is invalid for AMQP version \" << version.toString() << \".\";" + cr); + sb.append(indent + tab + "throw new ProtocolVersionException(ss.str());" + cr); + sb.append(indent + "}" + cr); + } + return sb.toString(); + } + + protected String generateMethodBodyCall(AmqpOrdinalFieldMap fieldMap, String methodBodyClassName, + AmqpVersion version, int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + String namespace = version != null ? version.namespace() + "::" : ""; + StringBuffer sb = new StringBuffer(indent + "out->send( new AMQFrame( channel," + cr); + sb.append(indent + tab + "new " + namespace + methodBodyClassName + "( parent->getProtocolVersion()"); + sb.append(generateMethodParameterList(fieldMap, indentSize + (5*tabSize), true, false, true)); + sb.append(" )));" + cr); + return sb.toString(); + } + + protected String generateMethodBodyIncludes(AmqpClass thisClass, int indentSize) + { + StringBuffer sb = new StringBuffer(); + if (thisClass != null) + { + sb.append(generateClassMethodBodyInclude(thisClass, indentSize)); + } + else + { + for (String thisClassName : model.classMap.keySet()) + { + thisClass = model.classMap.get(thisClassName); + sb.append(generateClassMethodBodyInclude(thisClass, indentSize)); + } + } + return sb.toString(); + } + + protected String generateClassMethodBodyInclude(AmqpClass thisClass, int indentSize) + { + StringBuffer sb = new StringBuffer(); + String indent = Utils.createSpaces(indentSize); + for (String thisMethodName : thisClass.methodMap.keySet()) + { + AmqpMethod method = thisClass.methodMap.get(thisMethodName); + sb.append(indent + "#include <" + thisClass.name + + Utils.firstUpper(method.name) + "Body.h>" + cr); + } + return sb.toString(); + } + + // Methods used for generation of code snippets for MethodBody class generation + + protected String getIndex(AmqpOrdinalVersionMap indexMap, AmqpVersion version) + throws AmqpTemplateException + { + for (Integer thisIndex : indexMap.keySet()) + { + AmqpVersionSet versionSet = indexMap.get(thisIndex); + if (versionSet.contains(version)) + return String.valueOf(thisIndex); + } + throw new AmqpTemplateException("Unable to find index for version " + version); + } + + protected String generateFieldDeclarations(AmqpFieldMap fieldMap, AmqpVersion version, int indentSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + if (version == null) + version = globalVersionSet.first(); + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, true, this); + for (Integer thisOrdinal : ordinalFieldMap.keySet()) + { + String[] fieldDomainPair = ordinalFieldMap.get(thisOrdinal); + sb.append(indent + fieldDomainPair[FIELD_CODE_TYPE] + " " + fieldDomainPair[FIELD_NAME] + ";" + cr); + } + return sb.toString(); + } + + protected String generateFieldGetMethods(AmqpFieldMap fieldMap, AmqpVersion version, int indentSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + if (version == null) + version = globalVersionSet.first(); + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, true, this); + for (Integer thisOrdinal : ordinalFieldMap.keySet()) + { + String[] fieldDomainPair = ordinalFieldMap.get(thisOrdinal); + sb.append(indent + "inline " + setRef(fieldDomainPair[FIELD_CODE_TYPE]) + " get" + + Utils.firstUpper(fieldDomainPair[FIELD_NAME]) + "() { return " + + fieldDomainPair[FIELD_NAME] + "; }" + cr); + } + return sb.toString(); + } + + protected String generatePrintMethodContents(AmqpFieldMap fieldMap, AmqpVersion version, int indentSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + if (version == null) + version = globalVersionSet.first(); + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, true, this); + boolean firstFlag = true; + for (Integer thisOrdinal : ordinalFieldMap.keySet()) + { + String[] fieldDomainPair = ordinalFieldMap.get(thisOrdinal); + String cast = fieldDomainPair[FIELD_CODE_TYPE].compareTo("u_int8_t") == 0 ? "(int)" : ""; + sb.append(indent + "out << \""); + if (!firstFlag) + sb.append("; "); + sb.append(fieldDomainPair[FIELD_NAME] + "=\" << " + cast + fieldDomainPair[FIELD_NAME] + ";" + cr); + firstFlag = false; + } + return sb.toString(); + } + + protected String generateBodySizeMethodContents(AmqpFieldMap fieldMap, AmqpVersion version, + int indentSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + ArrayList<String> bitFieldList = new ArrayList<String>(); + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, false, this); + Iterator<Integer> oItr = ordinalFieldMap.keySet().iterator(); + int ordinal = 0; + while (oItr.hasNext()) + { + ordinal = oItr.next(); + String[] fieldDomainPair = ordinalFieldMap.get(ordinal); + AmqpVersion thisVersion = version == null ? globalVersionSet.first() : version; + String domainType = getDomainType(fieldDomainPair[FIELD_CODE_TYPE], thisVersion); + + // Defer bit types by adding them to an array. When the first subsequent non-bit + // type is encountered, then handle the bits. This allows consecutive bits to be + // placed into the same byte(s) - 8 bits to the byte. + if (domainType.compareTo("bit") == 0) + { + bitFieldList.add(fieldDomainPair[FIELD_NAME]); + } + else + { + if (bitFieldList.size() > 0) // Handle accumulated bit types (if any) + { + sb.append(generateBitArrayBodySizeMethodContents(bitFieldList, ordinal, indentSize)); + } + sb.append(indent + "size += " + + typeMap.get(domainType).size.replaceAll("#", fieldDomainPair[FIELD_NAME]) + + "; /* " + fieldDomainPair[FIELD_NAME] + ": " + + domainType + " */" + cr); + } + } + if (bitFieldList.size() > 0) // Handle any remaining accumulated bit types + { + sb.append(generateBitArrayBodySizeMethodContents(bitFieldList, ordinal, indentSize)); + } + return sb.toString(); + } + + protected String generateBitArrayBodySizeMethodContents(ArrayList<String> bitFieldList, + int ordinal, int indentSize) + { + int numBytes = ((bitFieldList.size() - 1) / 8) + 1; + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String comment = bitFieldList.size() == 1 ? + bitFieldList.get(0) + ": bit" : + "Combinded bits: " + bitFieldList; + sb.append(indent + "size += " + + typeMap.get("bit").size.replaceAll("~", String.valueOf(numBytes)) + + "; /* " + comment + " */" + cr); + bitFieldList.clear(); + return sb.toString(); + } + + protected String generateEncodeMethodContents(AmqpFieldMap fieldMap, AmqpVersion version, + int indentSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + ArrayList<String> bitFieldList = new ArrayList<String>(); + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, false, this); + Iterator<Integer> oItr = ordinalFieldMap.keySet().iterator(); + int ordinal = 0; + while (oItr.hasNext()) + { + ordinal = oItr.next(); + String[] fieldDomainPair = ordinalFieldMap.get(ordinal); + AmqpVersion thisVersion = version == null ? globalVersionSet.first() : version; + String domainType = getDomainType(fieldDomainPair[FIELD_CODE_TYPE], thisVersion); + + // Defer bit types by adding them to an array. When the first subsequent non-bit + // type is encountered, then handle the bits. This allows consecutive bits to be + // placed into the same byte(s) - 8 bits to the byte. + if (domainType.compareTo("bit") == 0) + { + bitFieldList.add(fieldDomainPair[FIELD_NAME]); + } + else + { + if (bitFieldList.size() > 0) // Handle accumulated bit types (if any) + { + sb.append(generateBitEncodeMethodContents(bitFieldList, ordinal, indentSize)); + } + sb.append(indent + + typeMap.get(domainType).encodeExpression.replaceAll("#", fieldDomainPair[FIELD_NAME]) + + "; /* " + fieldDomainPair[FIELD_NAME] + ": " + domainType + " */"+ cr); + } + } + if (bitFieldList.size() > 0) // Handle any remaining accumulated bit types + { + sb.append(generateBitEncodeMethodContents(bitFieldList, ordinal, indentSize)); + } + + return sb.toString(); + } + + protected String generateBitEncodeMethodContents(ArrayList<String> bitFieldList, int ordinal, + int indentSize) + { + int numBytes = ((bitFieldList.size() - 1) / 8) + 1; + String indent = Utils.createSpaces(indentSize); + String bitArrayName = "flags_" + ordinal; + StringBuffer sb = new StringBuffer(indent + "u_int8_t " + bitArrayName + + "[" + numBytes + "] = {0};" + + (numBytes != 1 ? " /* All array elements will be initialized to 0 */" : "") + + cr); + for (int i=0; i<bitFieldList.size(); i++) + { + int bitIndex = i%8; + int byteIndex = i/8; + sb.append(indent + bitArrayName + "[" + byteIndex + "] |= " + bitFieldList.get(i) + + " << " + bitIndex + "; /* " + bitFieldList.get(i) + ": bit */" + cr); + } + for (int i=0; i<numBytes; i++) + { + sb.append(indent + "buffer.putOctet(" + bitArrayName + "[" + i + "]);" + cr); + } + bitFieldList.clear(); + return sb.toString(); + } + + protected String generateDecodeMethodContents(AmqpFieldMap fieldMap, AmqpVersion version, + int indentSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + ArrayList<String> bitFieldList = new ArrayList<String>(); + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, false, this); + Iterator<Integer> oItr = ordinalFieldMap.keySet().iterator(); + int ordinal = 0; + while (oItr.hasNext()) + { + ordinal = oItr.next(); + String[] fieldDomainPair = ordinalFieldMap.get(ordinal); + AmqpVersion thisVersion = version == null ? globalVersionSet.first() : version; + String domainType = getDomainType(fieldDomainPair[FIELD_CODE_TYPE], thisVersion); + + // Defer bit types by adding them to an array. When the first subsequent non-bit + // type is encountered, then handle the bits. This allows consecutive bits to be + // placed into the same byte(s) - 8 bits to the byte. + if (domainType.compareTo("bit") == 0) + { + bitFieldList.add(fieldDomainPair[FIELD_NAME]); + } + else + { + if (bitFieldList.size() > 0) // Handle accumulated bit types (if any) + { + sb.append(generateBitDecodeMethodContents(bitFieldList, ordinal, indentSize)); + } + sb.append(indent + + typeMap.get(domainType).decodeExpression.replaceAll("#", fieldDomainPair[FIELD_NAME]) + + "; /* " + fieldDomainPair[FIELD_NAME] + ": " + domainType + " */" + cr); + } + } + if (bitFieldList.size() > 0) // Handle any remaining accumulated bit types + { + sb.append(generateBitDecodeMethodContents(bitFieldList, ordinal, indentSize)); + } + + return sb.toString(); + } + + protected String generateBitDecodeMethodContents(ArrayList<String> bitFieldList, int ordinal, + int indentSize) + { + int numBytes = ((bitFieldList.size() - 1) / 8) + 1; + String indent = Utils.createSpaces(indentSize); + String bitArrayName = "flags_" + ordinal; + StringBuffer sb = new StringBuffer(indent + "u_int8_t " + bitArrayName + + "[" + numBytes + "];" + cr); + for (int i=0; i<numBytes; i++) + { + sb.append(indent + bitArrayName + "[" + i + "] = buffer.getOctet();" + cr); + } + for (int i=0; i<bitFieldList.size(); i++) + { + int bitIndex = i%8; + int byteIndex = i/8; + sb.append(indent + bitFieldList.get(i) + " = (1 << " + bitIndex + ") & " + + bitArrayName + "[" + byteIndex + "]; /* " + bitFieldList.get(i) + + ": bit */" + cr); + } + bitFieldList.clear(); + return sb.toString(); + } + + protected String generateFieldList(AmqpFieldMap fieldMap, AmqpVersion version, boolean defineFlag, + boolean initializerFlag, int indentSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, true, this); + Iterator<Integer> oItr = ordinalFieldMap.keySet().iterator(); + while (oItr.hasNext()) + { + int ordinal = oItr.next(); + String[] fieldDomainPair = ordinalFieldMap.get(ordinal); + sb.append(indent + (defineFlag ? setRef(fieldDomainPair[FIELD_CODE_TYPE]) + " " : "") + + fieldDomainPair[FIELD_NAME] + (initializerFlag ? "(" + fieldDomainPair[FIELD_NAME] + ")" : "") + + (oItr.hasNext() ? "," : "") + cr); + } + return sb.toString(); + } + + protected String generateMethodParameterList(AmqpOrdinalFieldMap fieldMap, int indentSize, + boolean leadingCommaFlag, boolean fieldTypeFlag, boolean fieldNameFlag) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + boolean first = true; + Iterator<Integer> pItr = fieldMap.keySet().iterator(); + while(pItr.hasNext()) + { + String[] field = fieldMap.get(pItr.next()); + if (first && leadingCommaFlag) + { + sb.append("," + (fieldNameFlag ? cr : " ")); + } + if (!first || leadingCommaFlag) + { + sb.append(indent); + } + sb.append( + (fieldTypeFlag ? setRef(field[FIELD_CODE_TYPE]) : "") + + (fieldNameFlag ? " " + field[FIELD_NAME] : "") + + (pItr.hasNext() ? "," + (fieldNameFlag ? cr : " ") : "")); + first = false; + } + return sb.toString(); + } + + protected String generateConstructor(AmqpClass thisClass, AmqpMethod method, + AmqpVersion version, int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + if (method.fieldMap.size() > 0) + { + sb.append(indent + thisClass.name + Utils.firstUpper(method.name) + "Body(ProtocolVersion& version," + cr); + sb.append(generateFieldList(method.fieldMap, version, true, false, 8)); + sb.append(indent + tab + ") :" + cr); + sb.append(indent + tab + "AMQMethodBody(version)," + cr); + sb.append(generateFieldList(method.fieldMap, version, false, true, 8)); + sb.append(indent + "{ }" + cr); + } + return sb.toString(); + } + + protected String generateServerOperationsInvoke(AmqpClass thisClass, AmqpMethod method, + AmqpVersion version, int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + + if (method.serverMethodFlagMap.size() > 0) // At least one AMQP version defines this method as a server method + { + Iterator<Boolean> bItr = method.serverMethodFlagMap.keySet().iterator(); + while (bItr.hasNext()) + { + if (bItr.next()) // This is a server operation + { + boolean fieldMapNotEmptyFlag = method.fieldMap.size() > 0; + sb.append(indent + "inline void invoke(AMQP_ServerOperations& target, u_int16_t channel)" + cr); + sb.append(indent + "{" + cr); + sb.append(indent + tab + "target.get" + thisClass.name + "Handler()->" + + parseForReservedWords(Utils.firstLower(method.name), + thisClass.name + Utils.firstUpper(method.name) + "Body.invoke()") + "(channel"); + if (fieldMapNotEmptyFlag) + { + sb.append("," + cr); + sb.append(generateFieldList(method.fieldMap, version, false, false, indentSize + 4*tabSize)); + sb.append(indent + tab + tab + tab + tab); + } + sb.append(");" + cr); + sb.append(indent + "}" + cr); + } + } + } + return sb.toString(); + } + + // Methods for generation of code snippets for amqp_methods.h/cpp files + + protected String generateMethodBodyIncludeList(AmqpModel model, int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + for (String thisClassName : model.classMap.keySet()) + { + AmqpClass thisClass = model.classMap.get(thisClassName); + for (String thisMethodName : thisClass.methodMap.keySet()) + { + AmqpMethod method = thisClass.methodMap.get(thisMethodName); + sb.append(indent + "#include \"" + thisClass.name + Utils.firstUpper(method.name) + "Body.h\"" + cr); + } + } + + return sb.toString(); + } + + protected String generateMethodBodyInstances(AmqpModel model, int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + for (String thisClassName : model.classMap.keySet()) + { + AmqpClass thisClass = model.classMap.get(thisClassName); + for (String thisMethodName : thisClass.methodMap.keySet()) + { + AmqpMethod method = thisClass.methodMap.get(thisMethodName); + sb.append(indent + "const " + thisClass.name + Utils.firstUpper(method.name) + "Body " + + Utils.firstLower(thisClass.name) + "_" + method.name + ";" + cr); + } + } + + return sb.toString(); + } + + protected String generateMethodBodyMapEntry(AmqpModel model, int indentSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + for (AmqpVersion version : globalVersionSet) + { + for (String thisClassName : model.classMap.keySet()) + { + AmqpClass thisClass = model.classMap.get(thisClassName); + for (String thisMethodName : thisClass.methodMap.keySet()) + { + AmqpMethod method = thisClass.methodMap.get(thisMethodName); + String namespace = method.isVersionConsistent(globalVersionSet) ? "" : version.namespace() + "::"; + try + { + int classOrdinal = thisClass.indexMap.getOrdinal(version); + int methodOrdinal = method.indexMap.getOrdinal(version); + String methodModyClassName = namespace + thisClass.name + Utils.firstUpper(method.name) + "Body"; + sb.append(indent + "insert(std::make_pair(createMapKey(" + classOrdinal + ", " + + methodOrdinal + ", " + version.getMajor() + ", " + version.getMinor() + + "), &createMethodBodyFn<" + methodModyClassName + ">));" + cr); + } + catch (AmqpTypeMappingException e) {} // ignore + } + } + } + + return sb.toString(); + } + + + // Helper functions + + private String generateVersionCheck(AmqpVersion version) + { + return "version.equals(" + version.getMajor() + ", " + version.getMinor() + ")"; + } + + private String generateVersionCheck(AmqpVersionSet versionSet) + throws AmqpTypeMappingException + { + StringBuffer sb = new StringBuffer(); + for (AmqpVersion v : versionSet) + { + if (!v.equals(versionSet.first())) + sb.append(" || "); + if (versionSet.size() > 1) + sb.append("("); + sb.append("version.equals(" + v.getMajor() + ", " + v.getMinor() + ")"); + if (versionSet.size() > 1) + sb.append(")"); + } + return sb.toString(); + } + + private String parseForReservedWords(String name, String context) + { + for (String cppReservedWord : cppReservedWords) + if (name.compareTo(cppReservedWord) == 0) + { + if (!quietFlag) + { + System.out.println("WARNING: " + (context == null ? "" : context + ": ") + + "Found XML method \"" + name + "\", which is a C++ reserved word. " + + "Changing generated name to \"" + name + "_\"."); + } + return name + "_"; + } + + for (String cppCommonDefine : cppCommonDefines) + if (name.compareTo(cppCommonDefine) == 0) + { + if (!quietFlag) + { + System.out.println("WARNING: " + (context == null ? "" : context + ": ") + + "Found XML method \"" + name + "\", which may clash with commonly used defines within C++. " + + "Changing generated name to \"" + name + "_\"."); + } + return name + "_"; + } + + return name; + } + + private String setRef(String codeType) + { + if (codeType.compareTo("string") == 0 || + codeType.compareTo("FieldTable") == 0) + return "const " + codeType + "&"; + return codeType; + } + + 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/src/org/apache/qpid/gentools/Generator.java index db75599b45..44f15cc71a 100644 --- a/gentools/org/apache/qpid/gentools/Generator.java +++ b/gentools/src/org/apache/qpid/gentools/Generator.java @@ -1,18 +1,21 @@ /* * - * 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. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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; @@ -26,13 +29,17 @@ 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 { + protected static String cr = Utils.lineSeparator; + protected static enum EnumConstOutputTypes { OUTPUT_STRING, OUTPUT_INTEGER, OUTPUT_DOUBLE; }; + // 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 static final int templateFileNameIndex = 0; + protected static final int templateStringIndex = 1; protected ArrayList<String[]> modelTemplateList; protected ArrayList<String[]> classTemplateList; @@ -42,6 +49,7 @@ public abstract class Generator implements LanguageConverter protected AmqpVersionSet globalVersionSet; protected AmqpDomainMap globalDomainMap; + protected AmqpConstantSet globalConstantSet; protected AmqpModel model; protected int generatedFileCounter; @@ -70,6 +78,16 @@ public abstract class Generator implements LanguageConverter { return globalDomainMap; } + + public void setConstantSet(AmqpConstantSet constantSet) + { + this.globalConstantSet = constantSet; + } + + public AmqpConstantSet getConstantSet() + { + return globalConstantSet; + } public void setModel(AmqpModel model) { @@ -88,44 +106,69 @@ public abstract class Generator implements LanguageConverter if (modelTemplateFiles.length > 0) { System.out.println("Model template file(s):"); - for (int t=0; t<modelTemplateFiles.length; t++) + for (File mtf : modelTemplateFiles) { - System.out.println(" " + modelTemplateFiles[t].getAbsolutePath()); - String template[] = {modelTemplateFiles[t].getName(), loadTemplate(modelTemplateFiles[t])}; + System.out.println(" " + mtf.getAbsolutePath()); + String template[] = {mtf.getName(), loadTemplate(mtf)}; modelTemplateList.add(template); } } if (classTemplatesFiles.length > 0) { System.out.println("Class template file(s):"); - for (int c=0; c<classTemplatesFiles.length; c++) + //for (int c=0; c<classTemplatesFiles.length; c++) + for (File ctf : classTemplatesFiles) { - System.out.println(" " + classTemplatesFiles[c].getAbsolutePath()); - String template[] = {classTemplatesFiles[c].getName(), loadTemplate(classTemplatesFiles[c])}; + System.out.println(" " + ctf.getAbsolutePath()); + String template[] = {ctf.getName(), loadTemplate(ctf)}; classTemplateList.add(template); } } if (methodTemplatesFiles.length > 0) { System.out.println("Method template file(s):"); - for (int m=0; m<methodTemplatesFiles.length; m++) + for (File mtf : methodTemplatesFiles) { - System.out.println(" " + methodTemplatesFiles[m].getAbsolutePath()); - String template[] = {methodTemplatesFiles[m].getName(), loadTemplate(methodTemplatesFiles[m])}; + System.out.println(" " + mtf.getAbsolutePath()); + String template[] = {mtf.getName(), loadTemplate(mtf)}; methodTemplateList.add(template); } } if (fieldTemplatesFiles.length > 0) { System.out.println("Field template file(s):"); - for (int f=0; f<fieldTemplatesFiles.length; f++) + for (File ftf : fieldTemplatesFiles) { - System.out.println(" " + fieldTemplatesFiles[f].getAbsolutePath()); - String template[] = {fieldTemplatesFiles[f].getName(), loadTemplate(fieldTemplatesFiles[f])}; + System.out.println(" " + ftf.getAbsolutePath()); + String template[] = {ftf.getName(), loadTemplate(ftf)}; fieldTemplateList.add(template); } } } + + abstract protected String prepareFilename(String filenameTemplate, AmqpClass thisClass, AmqpMethod method, + AmqpField field); + + abstract protected String processToken(String token, AmqpClass thisClass, AmqpMethod method, + AmqpField field, AmqpVersion version) + throws AmqpTemplateException, AmqpTypeMappingException; + + abstract protected void processClassList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpModel model) + throws AmqpTemplateException, AmqpTypeMappingException; + + abstract protected void processMethodList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpClass thisClass) + throws AmqpTemplateException, AmqpTypeMappingException; + + abstract protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpFieldMap fieldMap, AmqpVersion version) + throws AmqpTypeMappingException, AmqpTemplateException, IllegalAccessException, + InvocationTargetException; + + abstract protected void processConstantList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpConstantSet constantSet) + throws AmqpTemplateException, AmqpTypeMappingException; public void generate(File genDir) throws TargetDirectoryException, IOException, AmqpTypeMappingException, @@ -136,73 +179,53 @@ public abstract class Generator implements LanguageConverter this.genDir = genDir.getAbsolutePath(); // Use all model-level templates - for (int t = 0; t < classTemplateList.size(); t++) + for (String[] mt : modelTemplateList) { - processTemplate(modelTemplateList.get(t), null, null, null); + processTemplateA(mt); } // Cycle through classes - Set<String> ckeys = model.classMap.keySet(); - Iterator<String> citr = ckeys.iterator(); + Iterator<String> citr = model.classMap.keySet().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++) + for (String[] ct : classTemplateList) { - processTemplate(classTemplateList.get(c), thisClass, null, null); + processTemplateB(ct, thisClass); } // Cycle through all methods - Set<String> mkeys = thisClass.methodMap.keySet(); - Iterator<String> mitr = mkeys.iterator(); + Iterator<String> mitr = thisClass.methodMap.keySet().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++) + for (String[] mt : methodTemplateList) { - processTemplate(methodTemplateList.get(m), thisClass, method, null); + processTemplateC(mt, thisClass, method); } // Cycle through all fields - Set<String> fkeys = method.fieldMap.keySet(); - Iterator<String> fitr = fkeys.iterator(); + Iterator<String> fitr = method.fieldMap.keySet().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++) + for (String[] ft : fieldTemplateList) { - processTemplate(fieldTemplateList.get(f), thisClass, method, field); + processTemplateD(ft, 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 @@ -210,40 +233,47 @@ public abstract class Generator implements LanguageConverter 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++) + + for (AmqpVersion v : globalVersionSet) { // 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())); + if (isb.indexOf("${protocol-version-list-entry}") >= 0) + { + String versionListEntry = " { ${major}, ${minor} }" + + (v.equals(globalVersionSet.last()) ? "" : ","); + replaceToken(isb, "${protocol-version-list-entry}", String.valueOf(versionListEntry)); + } + if (isb.indexOf("${major}") >= 0) + replaceToken(isb, "${major}", String.valueOf(v.getMajor())); + if (isb.indexOf("${minor}") >= 0) + replaceToken(isb, "${minor}", String.valueOf(v.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 ++; - } + // Model-level template processing + abstract protected void processTemplateA(String[] template) + throws IOException, AmqpTemplateException, AmqpTypeMappingException, + IllegalAccessException, InvocationTargetException; + + // Class-level template processing + abstract protected void processTemplateB(String[] template, AmqpClass thisClass) + throws IOException, AmqpTemplateException, AmqpTypeMappingException, + IllegalAccessException, InvocationTargetException; + + // Method-level template processing + abstract protected void processTemplateC(String[] template, AmqpClass thisClass, + AmqpMethod method) + throws IOException, AmqpTemplateException, AmqpTypeMappingException, + IllegalAccessException, InvocationTargetException; + + // Field-level template processing + abstract protected void processTemplateD(String[] template, AmqpClass thisClass, + AmqpMethod method, AmqpField field) + throws IOException, AmqpTemplateException, AmqpTypeMappingException, + IllegalAccessException, InvocationTargetException; // Helper functions common to all generators @@ -268,7 +298,7 @@ public abstract class Generator implements LanguageConverter } - protected void processAllLists(StringBuffer sb, AmqpClass thisClass, AmqpMethod method) + protected void processAllLists(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, AmqpVersion version) throws AmqpTemplateException, AmqpTypeMappingException, IllegalAccessException, InvocationTargetException { @@ -297,8 +327,13 @@ public abstract class Generator implements LanguageConverter // 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)); + (method == null ? thisClass.fieldMap : method.fieldMap), + version); } + else if (listToken.compareTo("TLIST") == 0) + { + processConstantList(sb, lstart, lend + 1, globalConstantSet); + } else { throw new AmqpTemplateException("Unknown list token \"%{" + listToken + @@ -309,8 +344,9 @@ public abstract class Generator implements LanguageConverter } } - protected void processAllTokens(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, AmqpField field) - throws AmqpTemplateException + protected void processAllTokens(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, AmqpField field, + AmqpVersion version) + throws AmqpTemplateException, AmqpTypeMappingException { int lstart = sb.indexOf("${"); while (lstart != -1) @@ -319,7 +355,7 @@ public abstract class Generator implements LanguageConverter if (lend > 0) { String token = sb.substring(lstart, lend + 1); - replaceToken(sb, lstart, token, processToken(token, thisClass, method, field)); + replaceToken(sb, lstart, token, processToken(token, thisClass, method, field, version)); } lstart = sb.indexOf("${", lstart); } @@ -389,7 +425,8 @@ public abstract class Generator implements LanguageConverter while (line != null) { // Strip lines starting with '#' in template - treat these lines as template comments - if (line.length() > 0 && line.charAt(0) != '#') +// if (line.length() > 0 && line.charAt(0) != '#') // Bad idea - '#' used in C/C++ files (#include)! + if (line.length() > 0) sb.append(line + Utils.lineSeparator); else sb.append(Utils.lineSeparator); diff --git a/gentools/org/apache/qpid/gentools/JavaGenerator.java b/gentools/src/org/apache/qpid/gentools/JavaGenerator.java index dc19d0e14a..36b5f2f6d1 100644 --- a/gentools/org/apache/qpid/gentools/JavaGenerator.java +++ b/gentools/src/org/apache/qpid/gentools/JavaGenerator.java @@ -1,22 +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. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 java.lang.reflect.Method; import java.util.ArrayList; @@ -25,7 +30,9 @@ import java.util.TreeMap; public class JavaGenerator extends Generator { - static String cr = Utils.lineSeparator; + // TODO: Move this to parent class + protected static final int FIELD_NAME = 0; + protected static final int FIELD_CODE_TYPE = 1; private class DomainInfo { @@ -282,6 +289,11 @@ public class JavaGenerator extends Generator "~", // size "EncodingUtils.writeBooleans(buffer, #)", // encode expression "# = EncodingUtils.readBooleans(buffer)")); // decode expression + typeMap.put("content", new DomainInfo( + "Content", // Java code type + "EncodingUtils.encodedContentLength(#)", // size + "EncodingUtils.writeContentBytes(buffer, #)", // encode expression + "# = EncodingUtils.readContent(buffer)")); // decode expression typeMap.put("long", new DomainInfo( "long", // Java code type "4", // size @@ -293,15 +305,15 @@ public class JavaGenerator extends Generator "buffer.putLong(#)", // encode expression "# = buffer.getLong()")); // decode expression typeMap.put("longstr", new DomainInfo( - "String", // Java code type - "EncodingUtils.encodedLongStringLength(#)", // size + "byte[]", // Java code type + "EncodingUtils.encodedLongstrLength(#)", // size "EncodingUtils.writeLongStringBytes(buffer, #)", // encode expression - "# = EncodingUtils.readLongString(buffer)")); // decode expression + "# = EncodingUtils.readLongstr(buffer)")); // decode expression typeMap.put("octet", new DomainInfo( - "char", // Java code type + "short", // Java code type "1", // size - "buffer.putChar(#)", // encode expression - "# = buffer.getChar()")); // decode expression + "EncodingUtils.writeUnsignedByte(buffer, #)", // encode expression + "# = buffer.getUnsigned()")); // decode expression typeMap.put("short", new DomainInfo( "int", // Java code type "2", // size @@ -352,13 +364,21 @@ public class JavaGenerator extends Generator { 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; + { + throw new AmqpTypeMappingException("Domain type \"" + domainName + + "\" not found in Java typemap."); + } + DomainInfo info = typeMap.get(domainType); + if (info == null) + { + throw new AmqpTypeMappingException("Unknown domain: \"" + domainType + "\""); + } + return info.type; } // === Abstract methods from class Generator - Java-specific implementations === - + @Override protected String prepareFilename(String filenameTemplate, AmqpClass thisClass, AmqpMethod method, AmqpField field) @@ -372,10 +392,65 @@ public class JavaGenerator extends Generator replaceToken(sb, "${FIELD}", field.name); return sb.toString(); } + + @Override + protected void processTemplateA(String[] template) + throws IOException, AmqpTemplateException, AmqpTypeMappingException, + IllegalAccessException, InvocationTargetException + { + processTemplateD(template, null, null, null); + } + + @Override + protected void processTemplateB(String[] template, AmqpClass thisClass) + throws IOException, AmqpTemplateException, AmqpTypeMappingException, + IllegalAccessException, InvocationTargetException + { + processTemplateD(template, thisClass, null, null); + } + + @Override + protected void processTemplateC(String[] template, AmqpClass thisClass, + AmqpMethod method) + throws IOException, AmqpTemplateException, AmqpTypeMappingException, + IllegalAccessException, InvocationTargetException + { + processTemplateD(template, thisClass, method, null); + } + + @Override + protected void processTemplateD(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); + processTemplate(sb, thisClass, method, field, template[templateFileNameIndex], null); + writeTargetFile(sb, new File(genDir + Utils.fileSeparator + filename)); + generatedFileCounter ++; + } + + protected void processTemplate(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, + AmqpField field, String templateFileName, AmqpVersion version) + throws InvocationTargetException, IllegalAccessException, AmqpTypeMappingException + { + try { processAllLists(sb, thisClass, method, version); } + catch (AmqpTemplateException e) + { + System.out.println("WARNING: " + templateFileName + ": " + e.getMessage()); + } + try { processAllTokens(sb, thisClass, method, field, version); } + catch (AmqpTemplateException e) + { + System.out.println("WARNING: " + templateFileName + ": " + e.getMessage()); + } + } @Override - protected String processToken(String token, AmqpClass thisClass, AmqpMethod method, AmqpField field) - throws AmqpTemplateException + protected String processToken(String token, AmqpClass thisClass, AmqpMethod method, AmqpField field, + AmqpVersion version) + throws AmqpTemplateException, AmqpTypeMappingException { if (token.compareTo("${GENERATOR}") == 0) return generatorInfo; @@ -414,15 +489,16 @@ public class JavaGenerator extends Generator } @Override - protected void processClassList(StringBuffer sb, int tokStart, int tokEnd, AmqpModel model) - throws AmqpTemplateException + protected void processClassList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpModel model) + throws AmqpTemplateException, AmqpTypeMappingException { String codeSnippet; - int lend = sb.indexOf(cr, tokStart) + 1; // Include cr at end of line - String tline = sb.substring(tokEnd, lend); // Line excluding line marker, including cr - int tokxStart = tline.indexOf('$'); - String token = tline.substring(tokxStart).trim(); - sb.delete(tokStart, lend); + int lend = sb.indexOf(cr, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); if (token.compareTo("${reg_map_put_method}") == 0) { @@ -434,19 +510,20 @@ public class JavaGenerator extends Generator throw new AmqpTemplateException("Template token " + token + " unknown."); } - sb.insert(tokStart, codeSnippet); + sb.insert(listMarkerStartIndex, codeSnippet); } @Override - protected void processMethodList(StringBuffer sb, int tokStart, int tokEnd, AmqpClass thisClass) - throws AmqpTemplateException + protected void processMethodList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpClass thisClass) + throws AmqpTemplateException, AmqpTypeMappingException { String codeSnippet; - int lend = sb.indexOf(cr, tokStart) + 1; // Include cr at end of line - String tline = sb.substring(tokEnd, lend); // Line excluding line marker, including cr - int tokxStart = tline.indexOf('$'); - String token = tline.substring(tokxStart).trim(); - sb.delete(tokStart, lend); + int lend = sb.indexOf(cr, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); //TODO - we don't have any cases of this (yet). if (token.compareTo("${???}") == 0) @@ -458,20 +535,20 @@ public class JavaGenerator extends Generator throw new AmqpTemplateException("Template token " + token + " unknown."); } - sb.insert(tokStart, codeSnippet); + sb.insert(listMarkerStartIndex, codeSnippet); } @Override protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, - AmqpFieldMap fieldMap) + AmqpFieldMap fieldMap, AmqpVersion version) 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(); + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); sb.delete(listMarkerStartIndex, lend); // Field declarations - common to MethodBody and PropertyContentHeader classes @@ -489,8 +566,10 @@ public class JavaGenerator extends Generator } else if (token.compareTo("${mb_field_parameter_list}") == 0) { - // This is klunky... (cringe) TODO: Find a more elegant solution here sometime... + // <cringe> The code generated by this is ugly... It puts a comma on a line by itself! + // TODO: Find a more elegant solution here sometime... codeSnippet = fieldMap.size() > 0 ? Utils.createSpaces(42) + "," + cr : ""; + // </cringe> codeSnippet += fieldMap.parseFieldMap(mbParamListGenerateMethod, mbMangledParamListGenerateMethod, 42, 4, this); } @@ -568,7 +647,34 @@ public class JavaGenerator extends Generator } sb.insert(listMarkerStartIndex, codeSnippet); } - + + @Override + protected void processConstantList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpConstantSet constantSet) + throws AmqpTemplateException, AmqpTypeMappingException + + { + String codeSnippet; + int lend = sb.indexOf(cr, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + if (token.compareTo("${const_get_method}") == 0) + { + codeSnippet = generateConstantGetMethods(constantSet, 4, 4); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + + sb.insert(listMarkerStartIndex, codeSnippet); + } + + // === Protected and private helper functions unique to Java implementation === // Methods used for generation of code snippets called from the field map parsers @@ -601,7 +707,7 @@ public class JavaGenerator extends Generator return sb.toString(); } - protected String generateIndexInitializer(String mapName, AmqpOrdinalMap indexMap, int indentSize) + protected String generateIndexInitializer(String mapName, AmqpOrdinalVersionMap indexMap, int indentSize) { String indent = Utils.createSpaces(indentSize); StringBuffer sb = new StringBuffer(); @@ -631,51 +737,25 @@ public class JavaGenerator extends Generator 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 + for (AmqpVersion version : globalVersionSet) { - // Non-consistent indeces for all known versions - version-specific code required - sb.append(cr); - - Iterator<AmqpVersion> vItr = globalVersionSet.iterator(); - while (vItr.hasNext()) + // Find class and method index for this version (if it exists) + try { - 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 + int classIndex = findIndex(thisClass.indexMap, version); + int methodIndex = findIndex(method.indexMap, version); + sb.append(indent + "classIDMethodIDVersionBodyMap.put(" + cr); + sb.append(indent + tab + "createMapKey((short)" + classIndex + + ", (short)" + methodIndex + ", (byte)" + version.getMajor() + + ", (byte)" + version.getMinor() + "), " + cr); + sb.append(indent + tab + Utils.firstUpper(thisClass.name) + + Utils.firstUpper(method.name) + "Body.class);" + cr); } - sb.append(cr); + catch (Exception e) {} // Ignore } } } @@ -695,7 +775,110 @@ public class JavaGenerator extends Generator } throw new Exception("Index not found"); } - + + // Methods for AmqpConstants class + + protected String generateConstantGetMethods(AmqpConstantSet constantSet, + int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + Iterator<AmqpConstant> cItr = constantSet.iterator(); + while (cItr.hasNext()) + { + AmqpConstant constant = cItr.next(); + if (constant.isVersionConsistent(globalVersionSet)) + { + // return a constant + String value = constant.firstKey(); + sb.append(indent + "public static String " + constant.name + "() { return \"" + + constant.firstKey() + "\"; }" + cr); + if (Utils.containsOnlyDigits(value)) + { + sb.append(indent + "public static int " + constant.name + "AsInt() { return " + + constant.firstKey() + "; }" + cr); + } + if (Utils.containsOnlyDigitsAndDecimal(value)) + { + sb.append(indent + "public static double " + constant.name + "AsDouble() { return (double)" + + constant.firstKey() + "; }" + cr); + } + sb.append(cr); + } + else + { + // Return version-specific constant + sb.append(generateVersionDependentGet(constant, "String", "", "\"", "\"", indentSize, tabSize)); + sb.append(generateVersionDependentGet(constant, "int", "AsInt", "", "", indentSize, tabSize)); + sb.append(generateVersionDependentGet(constant, "double", "AsDouble", "(double)", "", indentSize, tabSize)); + sb.append(cr); + } + } + return sb.toString(); + } + + protected String generateVersionDependentGet(AmqpConstant constant, + String methodReturnType, String methodNameSuffix, String returnPrefix, String returnPostfix, + int indentSize, int tabSize) + throws AmqpTypeMappingException + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + sb.append(indent + "public static " + methodReturnType + " " + constant.name + + methodNameSuffix + "(byte major, byte minor) throws AMQProtocolVersionException" + cr); + sb.append(indent + "{" + cr); + boolean first = true; + Iterator<String> sItr = constant.keySet().iterator(); + while (sItr.hasNext()) + { + String value = sItr.next(); + AmqpVersionSet versionSet = constant.get(value); + sb.append(indent + tab + (first ? "" : "else ") + "if (" + generateVersionCheck(versionSet) + + ")" + cr); + sb.append(indent + tab + "{" + cr); + if (methodReturnType.compareTo("int") == 0 && !Utils.containsOnlyDigits(value)) + { + sb.append(generateConstantDeclarationException(constant.name, methodReturnType, + indentSize + (2*tabSize), tabSize)); + } + else if (methodReturnType.compareTo("double") == 0 && !Utils.containsOnlyDigitsAndDecimal(value)) + { + sb.append(generateConstantDeclarationException(constant.name, methodReturnType, + indentSize + (2*tabSize), tabSize)); + } + else + { + sb.append(indent + tab + tab + "return " + returnPrefix + value + returnPostfix + ";" + cr); + } + sb.append(indent + tab + "}" + cr); + first = false; + } + sb.append(indent + tab + "else" + cr); + sb.append(indent + tab + "{" + cr); + sb.append(indent + tab + tab + "throw new AMQProtocolVersionException(\"Constant \\\"" + + constant.name + "\\\" \" +" + cr); + sb.append(indent + tab + tab + tab + + "\"is undefined for AMQP version \" + major + \"-\" + minor + \".\");" + cr); + sb.append(indent + tab + "}" + cr); + sb.append(indent + "}" + cr); + return sb.toString(); + } + + protected String generateConstantDeclarationException(String name, String methodReturnType, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + sb.append(indent + "throw new AMQProtocolVersionException(\"Constant \\\"" + + name + "\\\" \" +" + cr); + sb.append(indent + tab + "\"cannot be converted to type " + methodReturnType + + " for AMQP version \" + major + \"-\" + minor + \".\");" + cr); + return sb.toString(); + } + // Methods for MessageBody classes protected String generateMbGetMethod(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) @@ -1427,7 +1610,7 @@ public class JavaGenerator extends Generator sb.append(" || "); if (versionArray.length > 1) sb.append("("); - sb.append("major == " + versionArray[i].getMajor() + " && minor == " + + sb.append("major == (byte)" + versionArray[i].getMajor() + " && minor == (byte)" + versionArray[i].getMinor()); if (versionArray.length > 1) sb.append(")"); diff --git a/gentools/src/org/apache/qpid/gentools/LanguageConverter.java b/gentools/src/org/apache/qpid/gentools/LanguageConverter.java new file mode 100644 index 0000000000..cb0a14e3bc --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/LanguageConverter.java @@ -0,0 +1,39 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 setConstantSet(AmqpConstantSet constantSet); + public AmqpConstantSet getConstantSet(); + + 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/src/org/apache/qpid/gentools/Main.java b/gentools/src/org/apache/qpid/gentools/Main.java new file mode 100644 index 0000000000..39fb6c3c45 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/Main.java @@ -0,0 +1,304 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; + +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 static final String defaultOutDir = ".." + Utils.fileSeparator + "gen"; + private static final String defaultCppTemplateDir = ".." + Utils.fileSeparator + "templ.cpp"; + private static final String defaultJavaTemplateDir = ".." + Utils.fileSeparator + "templ.java"; + + private DocumentBuilder docBuilder; + private AmqpVersionSet versionSet; + private Generator generator; + private AmqpConstantSet constants; + private AmqpDomainMap domainMap; + private AmqpModel model; + + private String outDir; + private String tmplDir; + private boolean javaFlag; + private ArrayList<String> xmlFiles; + private File[] modelTemplateFiles; + private File[] classTemplateFiles; + private File[] methodTemplateFiles; + private File[] fieldTemplateFiles; + + public Main() throws ParserConfigurationException + { + docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + versionSet = new AmqpVersionSet(); + xmlFiles = new ArrayList<String>(); + } + + public void run(String[] args) + throws IOException, + SAXException, + AmqpParseException, + AmqpTypeMappingException, + AmqpTemplateException, + TargetDirectoryException, + IllegalAccessException, + InvocationTargetException + { + modelTemplateFiles = new File[]{}; + classTemplateFiles = new File[]{}; + methodTemplateFiles = new File[]{}; + fieldTemplateFiles = new File[]{}; + + // 0. Initialize + outDir = defaultOutDir; + tmplDir = null; + javaFlag = true; + xmlFiles.clear(); + processArgs(args); + if (javaFlag) + prepareJava(); + else + prepareCpp(); + + if (modelTemplateFiles.length == 0 && classTemplateFiles.length == 0 && + methodTemplateFiles.length == 0 && fieldTemplateFiles.length == 0) + System.err.println(" WARNING: No template files."); + + // 1. Suck in all the XML spec files provided on the command line + analyzeXML(); + + // 2. Load up all templates + try + { + generator.initializeTemplates(modelTemplateFiles, classTemplateFiles, + methodTemplateFiles, fieldTemplateFiles); + } + catch (FileNotFoundException e) + { + System.err.println("Error: Unable to load template file (check -t option on command-line):"); + System.err.println(e.getMessage()); + return; + } + + // 3. Generate output + generator.generate(new File(outDir)); + + System.out.println("Files generated: " + generator.getNumberGeneratedFiles()); + System.out.println("Done."); + } + + private void processArgs(String[] args) + { + // Crude but simple... + for (int i=0; i<args.length; i++) + { + String arg = args[i]; + if (arg.charAt(0) == '-') + { + switch (arg.charAt(1)) + { + case 'c': + case 'C': + javaFlag = false; + break; + case 'j': + case 'J': + javaFlag = true; + break; + case 'o': + case 'O': + if (++i < args.length) + { + outDir = args[i]; + } + break; + case 't': + case 'T': + if (++i < args.length) + { + tmplDir = args[i]; + } + break; + } + } + else + { + xmlFiles.add(args[i]); + } + } + } + + private void prepareJava() + { + if (tmplDir == null) + tmplDir = defaultJavaTemplateDir; + System.out.println("Java generation mode."); + generator = new JavaGenerator(versionSet); + constants = new AmqpConstantSet(generator); + domainMap = new AmqpDomainMap(generator); + model = new AmqpModel(generator); + modelTemplateFiles = new File[] + { + new File(tmplDir + Utils.fileSeparator + "MethodRegistryClass.tmpl"), + new File(tmplDir + Utils.fileSeparator + "AmqpConstantsClass.tmpl"), + new File(tmplDir + Utils.fileSeparator + "ProtocolVersionListClass.tmpl") + }; + classTemplateFiles = new File[] + { +// new File(tmplDir + Utils.fileSeparator + "PropertyContentHeaderClass.tmpl") + }; + methodTemplateFiles = new File[] + { + new File(tmplDir + Utils.fileSeparator + "MethodBodyClass.tmpl") + }; + } + + private void prepareCpp() + { + if (tmplDir == null) + tmplDir = defaultCppTemplateDir; + System.out.println("C++ generation mode."); + generator = new CppGenerator(versionSet); + constants = new AmqpConstantSet(generator); + domainMap = new AmqpDomainMap(generator); + model = new AmqpModel(generator); + modelTemplateFiles = new File[] + { + new File(tmplDir + Utils.fileSeparator + "AMQP_ServerOperations.h.tmpl"), + new File(tmplDir + Utils.fileSeparator + "AMQP_ClientOperations.h.tmpl"), + new File(tmplDir + Utils.fileSeparator + "AMQP_ServerProxy.h.tmpl"), + new File(tmplDir + Utils.fileSeparator + "AMQP_ClientProxy.h.tmpl"), + new File(tmplDir + Utils.fileSeparator + "AMQP_ServerProxy.cpp.tmpl"), + new File(tmplDir + Utils.fileSeparator + "AMQP_ClientProxy.cpp.tmpl"), + new File(tmplDir + Utils.fileSeparator + "AMQP_Constants.h.tmpl"), + new File(tmplDir + Utils.fileSeparator + "AMQP_MethodVersionMap.h.tmpl"), + new File(tmplDir + Utils.fileSeparator + "AMQP_MethodVersionMap.cpp.tmpl"), + new File(tmplDir + Utils.fileSeparator + "AMQP_HighestVersion.cpp.tmpl") + }; + methodTemplateFiles = new File[] + { + new File(tmplDir + Utils.fileSeparator + "MethodBodyClass.h.tmpl") + }; + } + + private void analyzeXML() + throws IOException, SAXException, AmqpParseException, AmqpTypeMappingException + { + System.out.println("XML files: " + xmlFiles); + for (String filename : xmlFiles) + { + File f = new File(filename); + if (f.exists()) + { + // 1a. Initialize dom + System.out.print(" \"" + filename + "\":"); + Document doc = docBuilder.parse(new File(filename)); + 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 + constants.addFromNode(amqpNode, 0, version); + + // 1d. Extract domains + domainMap.addFromNode(amqpNode, 0, version); + + // 1e. Extract class/method/field heirarchy + model.addFromNode(amqpNode, 0, version); + } + else + System.err.println("ERROR: AMQP XML file \"" + filename + "\" 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); // List of loaded versions +// System.out.println(); +// constants.print(System.out, 0, 2); // List of constants +// System.out.println(); +// domainMap.print(System.out, 0, 2); // List of domains +// System.out.println(); +// model.print(System.out, 0, 2); // Internal version map model +// System.out.println(); +// System.out.println("*** End debug output ***"); +// System.out.println(); + } + + public static void main(String[] args) + { + // TODO: This is a simple and klunky way of hangling command-line args, and could be improved upon. + 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 [-o outDir] [-t tmplDir] XMLfile [XMLfile ...]"); + System.out.println(" where -c: Generate C++."); + System.out.println(" -j: Generate Java."); + System.out.println(" -o outDir: Use outDir as the output dir (default=\"" + defaultOutDir + "\")."); + System.out.println(" -t tmplDir: Find templates in tmplDir."); + System.out.println(" Defaults: \"" + defaultCppTemplateDir + "\" for C++;"); + System.out.println(" \"" + defaultJavaTemplateDir + "\" for java."); + System.out.println(" XMLfile is a space-separated list of AMQP XML files to be parsed."); + System.exit(0); + } + + public static String ListTemplateList(File[] list) + { + StringBuffer sb = new StringBuffer(); + for (int i=0; i<list.length; i++) + { + if (i != 0) + sb.append(", "); + sb.append(list[i].getName()); + } + return sb.toString(); + } +} diff --git a/gentools/org/apache/qpid/gentools/NodeAware.java b/gentools/src/org/apache/qpid/gentools/NodeAware.java index 859caf1d7e..a8f20f611a 100644 --- a/gentools/org/apache/qpid/gentools/NodeAware.java +++ b/gentools/src/org/apache/qpid/gentools/NodeAware.java @@ -1,18 +1,21 @@ /* * - * 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. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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; diff --git a/gentools/src/org/apache/qpid/gentools/Printable.java b/gentools/src/org/apache/qpid/gentools/Printable.java new file mode 100644 index 0000000000..a73878c506 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/Printable.java @@ -0,0 +1,28 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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/src/org/apache/qpid/gentools/TargetDirectoryException.java b/gentools/src/org/apache/qpid/gentools/TargetDirectoryException.java new file mode 100644 index 0000000000..cdaf381f0a --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/TargetDirectoryException.java @@ -0,0 +1,30 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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/src/org/apache/qpid/gentools/Utils.java b/gentools/src/org/apache/qpid/gentools/Utils.java new file mode 100644 index 0000000000..705e7dbf19 --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/Utils.java @@ -0,0 +1,145 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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_VALUE = "value"; + public final static String ATTRIBUTE_TYPE = "type"; // For compatibility with AMQP 8.0 + + public final static String ELEMENT_AMQP = "amqp"; + public final static String ELEMENT_CHASSIS = "chassis"; + public final static String ELEMENT_CLASS = "class"; + public final static String ELEMENT_CONSTANT = "constant"; + public final static String ELEMENT_DOMAIN = "domain"; + public final static String ELEMENT_METHOD = "method"; + public final static String ELEMENT_FIELD = "field"; + public final static String ELEMENT_VERSION = "version"; + + // 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)); + } + + // 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 + "\"."); + } + + // 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 firstLower(String str) + { + if (!Character.isUpperCase(str.charAt(0))) + return str; + StringBuffer sb = new StringBuffer(str); + sb.setCharAt(0, Character.toLowerCase(str.charAt(0))); + return sb.toString(); + } + + public static String createSpaces(int cnt) + { + StringBuffer sb = new StringBuffer(); + for (int i=0; i<cnt; i++) + sb.append(' '); + return sb.toString(); + } + + public static boolean containsOnlyDigits(String str) + { + boolean foundNonDigit = false; + for (int i=0; i<str.length() && !foundNonDigit; i++) + { + if (!Character.isDigit(str.charAt(i))) + { + foundNonDigit = true; + } + } + return !foundNonDigit; + } + + public static boolean containsOnlyDigitsAndDecimal(String str) + { + boolean foundNonDigit = false; + int decimalCntr = 0; + for (int i=0; i<str.length() && !foundNonDigit && decimalCntr<2; i++) + { + char ch = str.charAt(i); + if (!(Character.isDigit(ch) || ch == '.')) + { + foundNonDigit = true; + } + else if (ch == '.') + decimalCntr++; + } + return !foundNonDigit && decimalCntr<2; + } +} diff --git a/gentools/src/org/apache/qpid/gentools/VersionConsistencyCheck.java b/gentools/src/org/apache/qpid/gentools/VersionConsistencyCheck.java new file mode 100644 index 0000000000..1f6b9f1a6d --- /dev/null +++ b/gentools/src/org/apache/qpid/gentools/VersionConsistencyCheck.java @@ -0,0 +1,26 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 VersionConsistencyCheck +{ + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet); +} diff --git a/gentools/templ.java/AmqpConstantsClass.tmpl b/gentools/templ.java/AmqpConstantsClass.tmpl new file mode 100644 index 0000000000..8d459f2977 --- /dev/null +++ b/gentools/templ.java/AmqpConstantsClass.tmpl @@ -0,0 +1,37 @@ +&{AmqpConstants.java} +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/* + * This file is auto-generated by ${GENERATOR} - do not modify. + * Supported AMQP versions: +%{VLIST} * ${major}-${minor} + */ + +package org.apache.qpid.framing; + +class AmqpConstants +{ + // Constant getValue methods + +%{TLIST} ${const_get_method} + +} diff --git a/gentools/templ.java/MethodBodyClass.tmpl b/gentools/templ.java/MethodBodyClass.tmpl index a693adf9a5..ad1ce36006 100644 --- a/gentools/templ.java/MethodBodyClass.tmpl +++ b/gentools/templ.java/MethodBodyClass.tmpl @@ -1,19 +1,22 @@ &{${CLASS}${METHOD}Body.java} /* * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. * */ @@ -51,6 +54,8 @@ ${METHOD_ID_INIT} public int getClazz() { return classIdMap.get(major + "-" + minor); } public int getMethod() { return methodIdMap.get(major + "-" + minor); } + public static int getClazz(byte major, byte minor) { return classIdMap.get(major + "-" + minor); } + public static int getMethod(byte major, byte minor) { return methodIdMap.get(major + "-" + minor); } // Field methods %{FLIST} ${mb_field_get_method} diff --git a/gentools/templ.java/MethodRegistryClass.tmpl b/gentools/templ.java/MethodRegistryClass.tmpl index d68ea28056..0f15918f90 100644 --- a/gentools/templ.java/MethodRegistryClass.tmpl +++ b/gentools/templ.java/MethodRegistryClass.tmpl @@ -1,19 +1,22 @@ &{MainRegistry.java} /* * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. * */ @@ -25,12 +28,53 @@ package org.apache.qpid.framing; -import java.util.Map; +import java.util.HashMap; +import java.lang.reflect.Constructor; +import org.apache.log4j.Logger; class MainRegistry { - static void register(Map map, byte major, byte minor) + private static final Logger _log = Logger.getLogger(MainRegistry.class); + private static HashMap<Long, Class> classIDMethodIDVersionBodyMap = new HashMap<Long, Class>(); + + static { %{CLIST} ${reg_map_put_method} } + + public static AMQMethodBody get(short classID, short methodID, byte major, byte minor) + throws AMQFrameDecodingException + { + Class bodyClass = classIDMethodIDVersionBodyMap.get( + createMapKey(classID, methodID, major, minor)); + if (bodyClass == null) + { + throw new AMQFrameDecodingException(_log, + "Unable to find a suitable decoder for class " + classID + " and method " + + methodID + " in AMQP version " + major + "-" + minor + "."); + } + try + { + Constructor initFn = bodyClass.getConstructor(byte.class, byte.class); + return (AMQMethodBody) initFn.newInstance(major, minor); + } + catch (Exception e) + { + throw new AMQFrameDecodingException(_log, + "Unable to instantiate body class for class " + classID + " and method " + + methodID + " in AMQP version " + major + "-" + minor + " : " + e, e); + } + } + + private static Long createMapKey(short classID, short methodID, byte major, byte minor) + { + /** + * Mapping of 4 components into a guaranteed unique key: + * MSB LSB + * +----+----+----+----+----+----+-----+-----+ + * | 0 | classID |methodID |major|minor| + * +----+----+----+----+----+----+-----+-----+ + */ + return new Long(((long)classID << 32) + ((long)methodID << 16) + ((long)major << 8) + minor); + } } diff --git a/gentools/templ.java/PropertyContentHeaderClass.tmpl b/gentools/templ.java/PropertyContentHeaderClass.tmpl index bae99a4187..3c147cf6b6 100644 --- a/gentools/templ.java/PropertyContentHeaderClass.tmpl +++ b/gentools/templ.java/PropertyContentHeaderClass.tmpl @@ -1,19 +1,22 @@ -&{${CLASS}PropertyContentHeader.java} +&{${CLASS}ContentHeaderProperties.java} /* * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. * */ @@ -28,7 +31,7 @@ package org.apache.qpid.framing; import org.apache.log4j.Logger; import org.apache.mina.common.ByteBuffer; -class ${CLASS}ContentHeaderProperties implements ContentHeaderProperties +public class ${CLASS}ContentHeaderProperties implements ContentHeaderProperties { private static final Logger logger = Logger.getLogger(BasicContentHeaderProperties.class); diff --git a/gentools/templ.java/ProtocolVersionListClass.tmpl b/gentools/templ.java/ProtocolVersionListClass.tmpl new file mode 100644 index 0000000000..bc98e0c1ea --- /dev/null +++ b/gentools/templ.java/ProtocolVersionListClass.tmpl @@ -0,0 +1,38 @@ +&{ProtocolVersionList.java} +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/* + * This file is auto-generated by ${GENERATOR} - do not modify. + * Supported AMQP versions: +%{VLIST} * ${major}-${minor} + */ + +package org.apache.qpid.framing; + +public interface ProtocolVersionList +{ + public final int PROTOCOL_MAJOR = 0; + public final int PROTOCOL_MINOR = 1; + public final byte pv[][] = { +%{VLIST} ${protocol-version-list-entry} + }; +} |