- Enahnced the Alt java generator so that all messages implement PBMessage
- classes created by an enum can now be queried by the associated enum value.



git-svn-id: https://svn.apache.org/repos/asf/activemq/activemq-protobuf/trunk@752441 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/PBMessage.java b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/PBMessage.java
new file mode 100644
index 0000000..6996f67
--- /dev/null
+++ b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/PBMessage.java
@@ -0,0 +1,23 @@
+/**
+ * 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.activemq.protobuf;
+
+public interface PBMessage <Bean, Buffer extends MessageBuffer>{
+    public Bean copy();
+    public boolean frozen();
+    public Buffer freeze();
+}
diff --git a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/AltJavaGenerator.java b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/AltJavaGenerator.java
index 9745f71..85024f7 100644
--- a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/AltJavaGenerator.java
+++ b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/AltJavaGenerator.java
@@ -247,8 +247,15 @@
         if( multipleFiles && m.getParent()==null ) {
             staticOption="";
         }
-                
-        p(staticOption+"public interface " + className +" {");
+
+        String extendsClause = " extends org.apache.activemq.protobuf.PBMessage<"+className+"."+beanClassName+", "+className+"."+bufferClassName+">";
+        for (EnumFieldDescriptor enumFeild : m.getAssociatedEnumFieldDescriptors()) {
+            String name = uCamel(enumFeild.getParent().getName());
+            name = name+"."+name+"Creatable";
+            extendsClause += ", "+name; 
+        }
+        
+        p(staticOption+"public interface " + className + extendsClause +" {");
         p();
         indent();
         
@@ -337,6 +344,16 @@
         generateMethodClear(m);
         
         generateReadWriteExternal(m);
+        
+        for (EnumFieldDescriptor enumFeild : m.getAssociatedEnumFieldDescriptors()) {
+            String enumName = uCamel(enumFeild.getParent().getName());
+            p("public "+enumName+" to"+enumName+"() {");
+            indent();
+            p("return "+enumName+"."+enumFeild.getName()+";");
+            unindent();
+            p("}");
+            p();            
+        }        
 
         unindent();
         p("}");
@@ -425,6 +442,22 @@
         
         generateBufferEquals(m, bufferClassName);
 
+        p("public boolean frozen() {");
+        indent();
+        p("return true;");
+        unindent();
+        p("}");
+
+        for (EnumFieldDescriptor enumFeild : m.getAssociatedEnumFieldDescriptors()) {
+            String enumName = uCamel(enumFeild.getParent().getName());
+            p("public "+enumName+" to"+enumName+"() {");
+            indent();
+            p("return "+enumName+"."+enumFeild.getName()+";");
+            unindent();
+            p("}");
+            p();            
+        }        
+        
         unindent();
         p("}");
         p();
@@ -1542,11 +1575,9 @@
             }
         }
         
-        
-        
-        
         unindent();
         p("}");
+        p();            
         
     }
     
@@ -2062,13 +2093,20 @@
         String createMessage = getOption(ed.getOptions(), "java_create_message", null);        
         if( "true".equals(createMessage) ) {
             
-            p("public Object createBean() {");
+            p("public interface "+uname+"Creatable {");
+            indent();
+            p(""+uname+" to"+uname+"();");
+            unindent();
+            p("}");
+            p();
+            
+            p("public "+uname+"Creatable createBean() {");
             indent();
             p("switch (this) {");
             indent();
             for (EnumFieldDescriptor field : ed.getFields().values()) {
                 p("case "+field.getName()+":");
-                String type = constantToUCamelCase(field.getName());
+                String type = field.getAssociatedType().getName();
                 p("   return new "+type+"."+type+"Bean();");
             }
             p("default:");
diff --git a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/EnumDescriptor.java b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/EnumDescriptor.java
index b392fad..3e6e195 100644
--- a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/EnumDescriptor.java
+++ b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/EnumDescriptor.java
@@ -52,9 +52,56 @@
         return protoDescriptor;
     }
 
+    private String getOption(Map<String, OptionDescriptor> options, String optionName, String defaultValue) {
+        OptionDescriptor optionDescriptor = options.get(optionName);
+        if (optionDescriptor == null) {
+            return defaultValue;
+        }
+        return optionDescriptor.getValue();
+    }
+    
+    private String constantToUCamelCase(String name) {
+        boolean upNext=true;
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < name.length(); i++) {
+            char c = name.charAt(i);
+            if( Character.isJavaIdentifierPart(c) && Character.isLetterOrDigit(c)) {
+                if( upNext ) {
+                    c = Character.toUpperCase(c);
+                    upNext=false;
+                } else {
+                    c = Character.toLowerCase(c);
+                }
+                sb.append(c);
+            } else {
+                upNext=true;
+            }
+        }
+        return sb.toString();
+    }
+    
     public void validate(List<String> errors) {
-        // TODO Auto-generated method stub
-        
+        String createMessage = getOption(getOptions(), "java_create_message", null);        
+        if( "true".equals(createMessage) ) {
+            for (EnumFieldDescriptor field : getFields().values()) {
+                String type = constantToUCamelCase(field.getName());
+                
+                TypeDescriptor typeDescriptor=null;
+                // Find the type def for that guy..
+                if( parent!=null ) {
+                    typeDescriptor = parent.getType(type);
+                }
+                if( typeDescriptor == null ) {
+                    typeDescriptor = protoDescriptor.getType(type);
+                }
+                if( typeDescriptor == null ) {
+                    errors.add("ENUM constant '"+field.getName()+"' did not find expected associated message: "+type);
+                } else {
+                    field.associate(typeDescriptor);
+                    typeDescriptor.associate(field);
+                }
+            }
+        }
     }
 
     public MessageDescriptor getParent() {
@@ -81,5 +128,9 @@
         this.options = options;
     }
 
+    public void associate(EnumFieldDescriptor desc) {
+        throw new RuntimeException("not supported.");
+    }
+
 
 }
diff --git a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/EnumFieldDescriptor.java b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/EnumFieldDescriptor.java
index e011c9c..694492a 100644
--- a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/EnumFieldDescriptor.java
+++ b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/EnumFieldDescriptor.java
@@ -21,7 +21,8 @@
     private String name;
     private int value;
     private final EnumDescriptor parent;
-
+    private TypeDescriptor associatedType;
+    
     public EnumFieldDescriptor(EnumDescriptor parent) {
         this.parent = parent;
     }
@@ -46,4 +47,12 @@
         return parent;
     }
 
+    public TypeDescriptor getAssociatedType() {
+        return associatedType;
+    }
+
+    public void associate(TypeDescriptor associatedType) {
+        this.associatedType = associatedType;
+    }
+
 }
diff --git a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/MessageDescriptor.java b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/MessageDescriptor.java
index e512f48..c407b44 100644
--- a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/MessageDescriptor.java
+++ b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/MessageDescriptor.java
@@ -35,6 +35,8 @@
     private final ProtoDescriptor protoDescriptor;
     private List<MessageDescriptor> extendsList = new ArrayList<MessageDescriptor>();
     private Map<String, OptionDescriptor> options = new LinkedHashMap<String, OptionDescriptor>();
+    private List<EnumFieldDescriptor> associatedEnumFieldDescriptors = new ArrayList<EnumFieldDescriptor>();
+    
     private final MessageDescriptor parent;
 	private MessageDescriptor baseType;
 
@@ -183,4 +185,12 @@
 		return baseType;
 	}
 
+    public void associate(EnumFieldDescriptor desc) {
+        associatedEnumFieldDescriptors.add(desc);
+    }
+
+    public List<EnumFieldDescriptor> getAssociatedEnumFieldDescriptors() {
+        return associatedEnumFieldDescriptors;
+    }
+
 }
diff --git a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/TypeDescriptor.java b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/TypeDescriptor.java
index e280b50..6e47738 100644
--- a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/TypeDescriptor.java
+++ b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/TypeDescriptor.java
@@ -25,4 +25,6 @@
 
     public boolean isEnum();
 
+    public void associate(EnumFieldDescriptor desc);
+    
 }