You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kp...@apache.org on 2007/01/16 20:53:56 UTC

svn commit: r496841 - in /incubator/qpid/trunk/qpid/gentools: src/org/apache/qpid/gentools/DotnetGenerator.java src/org/apache/qpid/gentools/JavaGenerator.java src/org/apache/qpid/gentools/Main.java templ.net/

Author: kpvdr
Date: Tue Jan 16 11:53:55 2007
New Revision: 496841

URL: http://svn.apache.org/viewvc?view=rev&rev=496841
Log:
Added .NET generator class to the code generator, and added mechanism to invoke it from the command line. The DotnetGenerator class is still mostly empty (ie has no code generation methods). The next step is to plan the templates that are required for .NET, and then implement them alongside the generator class code snippet methods.

Added:
    incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/DotnetGenerator.java
    incubator/qpid/trunk/qpid/gentools/templ.net/
Modified:
    incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/JavaGenerator.java
    incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/Main.java

Added: incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/DotnetGenerator.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/DotnetGenerator.java?view=auto&rev=496841
==============================================================================
--- incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/DotnetGenerator.java (added)
+++ incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/DotnetGenerator.java Tue Jan 16 11:53:55 2007
@@ -0,0 +1,319 @@
+package org.apache.qpid.gentools;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.TreeMap;
+
+public class DotnetGenerator extends Generator
+{
+	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 DotnetGenerator(AmqpVersionSet versionList)
+	{
+		super(versionList);
+		// Load .NET 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).
+		// TODO: I have left a copy of the Java typeMap here - replace with appropriate .NET values.
+		typeMap.put("bit", new DomainInfo(
+			"boolean",										// .NET code type
+			"~",											// size
+			"EncodingUtils.writeBooleans(buffer, #)",		// encode expression
+			"# = EncodingUtils.readBooleans(buffer)"));		// decode expression
+		typeMap.put("content", new DomainInfo(
+			"Content",										// .NET code type
+			"EncodingUtils.encodedContentLength(#)", 	// size
+			"EncodingUtils.writeContentBytes(buffer, #)", // encode expression
+			"# = EncodingUtils.readContent(buffer)"));	// decode expression
+		typeMap.put("long", new DomainInfo(
+			"long",											// .NET code type
+			"4",											// size
+			"EncodingUtils.writeUnsignedInteger(buffer, #)", // encode expression
+			"# = buffer.getUnsignedInt()")); 				// decode expression
+		typeMap.put("longlong", new DomainInfo(
+			"long",											// .NET code type
+			"8",											// size
+			"buffer.putLong(#)", 							// encode expression
+			"# = buffer.getLong()")); 						// decode expression
+		typeMap.put("longstr", new DomainInfo(
+			"byte[]",										// .NET code type
+			"EncodingUtils.encodedLongstrLength(#)", 		// size
+			"EncodingUtils.writeLongStringBytes(buffer, #)", // encode expression
+			"# = EncodingUtils.readLongstr(buffer)"));		// decode expression
+		typeMap.put("octet", new DomainInfo(
+			"short",										// .NET code type
+			"1",											// size
+			"EncodingUtils.writeUnsignedByte(buffer, #)",	// encode expression
+			"# = buffer.getUnsigned()")); 					// decode expression
+		typeMap.put("short", new DomainInfo(
+			"int",											// .NET code type
+			"2",											// size
+			"EncodingUtils.writeUnsignedShort(buffer, #)",	// encode expression
+			"# = buffer.getUnsignedShort()")); 				// decode expression
+		typeMap.put("shortstr", new DomainInfo(
+			"AMQShortString",								// .NET code type
+			"EncodingUtils.encodedShortStringLength(#)",	// size
+			"EncodingUtils.writeShortStringBytes(buffer, #)", // encode expression
+			"# = EncodingUtils.readAMQShortString(buffer)"));	// decode expression
+		typeMap.put("table", new DomainInfo(
+			"FieldTable",									// .NET code type
+			"EncodingUtils.encodedFieldTableLength(#)", 	// size
+			"EncodingUtils.writeFieldTableBytes(buffer, #)", // encode expression
+			"# = EncodingUtils.readFieldTable(buffer)"));	// decode expression
+		typeMap.put("timestamp", new DomainInfo(
+			"long",											// .NET code type
+			"8",											// size
+			"EncodingUtils.writeTimestamp(buffer, #)",		// encode expression
+			"# = EncodingUtils.readTimestamp(buffer)"));	// decode expression
+	}
+
+	@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 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 tokStart = tline.indexOf('$');
+		String token = tline.substring(tokStart).trim();
+		sb.delete(listMarkerStartIndex, lend);
+		
+		// TODO: Add in tokens and calls to their corresponding generator methods here...
+		if (token.compareTo("${??????????}") == 0)
+		{
+			codeSnippet = token; // This is a stub to get the compile working - remove when gen method is present.
+//			codeSnippet = generateRegistry(model, 8, 4); 
+		}
+		
+		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 tokStart = tline.indexOf('$');
+        String token = tline.substring(tokStart).trim();
+        sb.delete(listMarkerStartIndex, lend);
+
+		// TODO: Add in tokens and calls to their corresponding generator methods here...
+        if (token.compareTo("${??????????}") == 0)
+        {
+			codeSnippet = token; // This is a stub to get the compile working - remove when gen method is present.
+//            codeSnippet = generateConstantGetMethods(constantSet, 4, 4); 
+        }
+       
+        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 tokStart = tline.indexOf('$');
+		String token = tline.substring(tokStart).trim();
+		sb.delete(listMarkerStartIndex, lend);
+		
+		// TODO: Add in tokens and calls to their corresponding generator methods here...
+		if (token.compareTo("${??????????}") == 0)
+		{
+			codeSnippet = token; // This is a stub to get the compile working - remove when gen method is present.
+//			codeSnippet = fieldMap.parseFieldMap(declarationGenerateMethod,
+//				mangledDeclarationGenerateMethod, 4, 4, this);
+		}
+		
+		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 tokStart = tline.indexOf('$');
+		String token = tline.substring(tokStart).trim();
+		sb.delete(listMarkerStartIndex, lend);
+		
+		// TODO: Add in tokens and calls to their corresponding generator methods here...
+		if (token.compareTo("${??????????}") == 0)
+		{
+			codeSnippet = token; // This is a stub to get the compile working - remove when gen method is present.
+		}
+		
+		else // Oops!
+		{
+			throw new AmqpTemplateException("Template token " + token + " unknown.");
+		}
+		sb.insert(listMarkerStartIndex, codeSnippet);
+	}
+
+	@Override
+	protected void processTemplateA(String[] template) throws IOException,
+			AmqpTemplateException, AmqpTypeMappingException,
+			IllegalAccessException, InvocationTargetException
+	{
+		// I've put in the Java model here - this can be changed if a different pattern is required.
+		processTemplateD(template, null, null, null);
+	}
+
+	@Override
+	protected void processTemplateB(String[] template, AmqpClass thisClass)
+			throws IOException, AmqpTemplateException,
+			AmqpTypeMappingException, IllegalAccessException,
+			InvocationTargetException
+	{
+		// I've put in the Java model here - this can be changed if a different pattern is required.
+		processTemplateD(template, thisClass, null, null);
+	}
+
+	@Override
+	protected void processTemplateC(String[] template, AmqpClass thisClass,
+			AmqpMethod method) throws IOException, AmqpTemplateException,
+			AmqpTypeMappingException, IllegalAccessException,
+			InvocationTargetException
+	{
+		// I've put in the Java model here - this can be changed if a different pattern is required.
+		processTemplateD(template, thisClass, method, null);
+	}
+
+	@Override
+	protected void processTemplateD(String[] template, AmqpClass thisClass,
+			AmqpMethod method, AmqpField field) throws IOException,
+			AmqpTemplateException, AmqpTypeMappingException,
+			IllegalAccessException, InvocationTargetException
+	{
+		// I've put in the Java model here - this can be changed if a different pattern is required.
+		StringBuffer sb = new StringBuffer(template[1]);
+		String filename = prepareFilename(getTemplateFileName(sb), thisClass, method, field);
+		try { processAllLists(sb, thisClass, method, null); }
+		catch (AmqpTemplateException e)
+		{
+			System.out.println("WARNING: " + template[templateFileNameIndex] + ": " + e.getMessage());
+		}
+		try { processAllTokens(sb, thisClass, method, field, null); }
+		catch (AmqpTemplateException e)
+		{
+			System.out.println("WARNING: " + template[templateFileNameIndex] + ": " + e.getMessage());
+		}
+		writeTargetFile(sb, new File(genDir + Utils.fileSeparator + filename));
+		generatedFileCounter ++;
+	}
+
+	@Override
+	protected String processToken(String token, AmqpClass thisClass,
+			AmqpMethod method, AmqpField field, AmqpVersion version)
+			throws AmqpTemplateException, AmqpTypeMappingException
+	{
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public String getDomainType(String domainName, AmqpVersion version)
+			throws AmqpTypeMappingException
+	{
+		return globalDomainMap.getDomainType(domainName, version);
+	}
+
+	public String getGeneratedType(String domainName, AmqpVersion version)
+			throws AmqpTypeMappingException
+	{
+		String domainType = globalDomainMap.getDomainType(domainName, version);
+		if (domainType == null)
+        {
+			throw new AmqpTypeMappingException("Domain type \"" + domainName +
+                "\" not found in Java typemap.");
+        }
+        DomainInfo info = typeMap.get(domainType);
+        if (info == null)
+        {
+            throw new AmqpTypeMappingException("Unknown domain: \"" + domainType + "\"");
+        }
+		return info.type;
+	}
+
+	public String prepareClassName(String className)
+	{
+		return camelCaseName(className, true);
+	}
+
+	public String prepareDomainName(String domainName)
+	{
+		return camelCaseName(domainName, false);
+	}
+
+	public String prepareMethodName(String methodName)
+	{
+		return camelCaseName(methodName, false);
+	}
+
+	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();
+	}
+}

Modified: incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/JavaGenerator.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/JavaGenerator.java?view=diff&rev=496841&r1=496840&r2=496841
==============================================================================
--- incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/JavaGenerator.java (original)
+++ incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/JavaGenerator.java Tue Jan 16 11:53:55 2007
@@ -1072,7 +1072,7 @@
 				line.append(bitFieldList.get(i));
 			}
 			
-			sb.append(Utils.createSpaces(indentSize) +
+			sb.append(indent +
 				typeMap.get("bit").encodeExpression.replaceAll("#", line.toString()) + ";" + cr);
 		}
 		return sb.toString();

Modified: incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/Main.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/Main.java?view=diff&rev=496841&r1=496840&r2=496841
==============================================================================
--- incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/Main.java (original)
+++ incubator/qpid/trunk/qpid/gentools/src/org/apache/qpid/gentools/Main.java Tue Jan 16 11:53:55 2007
@@ -38,8 +38,11 @@
 {
     private static final String defaultOutDir = ".." + Utils.fileSeparator + "gen";
     private static final String defaultCppTemplateDir = ".." + Utils.fileSeparator + "templ.cpp";
+    private static final String defaultDotnetTemplateDir = ".." + Utils.fileSeparator + "templ.net";
     private static final String defaultJavaTemplateDir = ".." + Utils.fileSeparator + "templ.java";
     
+    private enum GeneratorLangEnum { CPP, DOTNET, JAVA }
+    
 	private DocumentBuilder docBuilder;
 	private AmqpVersionSet versionSet;
 	private Generator generator;
@@ -49,7 +52,7 @@
     
     private String outDir;
     private String tmplDir;
-    private boolean javaFlag;
+    private GeneratorLangEnum generatorLang;
     private ArrayList<String> xmlFiles;
     private File[] modelTemplateFiles;
     private File[] classTemplateFiles;
@@ -81,13 +84,20 @@
         // 0. Initialize
         outDir = defaultOutDir;
         tmplDir = null;
-        javaFlag = true;
+        generatorLang = GeneratorLangEnum.CPP; // Default generation language
         xmlFiles.clear();
         processArgs(args);
-		if (javaFlag)
-            prepareJava();
-        else
+        switch (generatorLang)
+        {
+        case JAVA:
+        	prepareJava();
+        	break;
+        case DOTNET:
+        	prepareDotnet();
+        	break;
+        default:
             prepareCpp();
+        }
 
 		if (modelTemplateFiles.length == 0 && classTemplateFiles.length == 0 &&
 			methodTemplateFiles.length == 0 && fieldTemplateFiles.length == 0)
@@ -128,11 +138,15 @@
                 {
                     case 'c':
                     case 'C':
-                        javaFlag = false;
+                    	generatorLang = GeneratorLangEnum.CPP;
                         break;
                     case 'j':
                     case 'J':
-                        javaFlag = true;
+                    	generatorLang = GeneratorLangEnum.JAVA;
+                        break;
+                    case 'n':
+                    case 'N':
+                    	generatorLang = GeneratorLangEnum.DOTNET;
                         break;
                     case 'o':
                     case 'O':
@@ -182,6 +196,30 @@
         };
     }
     
+    private void prepareDotnet()
+    {
+        if (tmplDir == null)
+            tmplDir = defaultDotnetTemplateDir;
+        System.out.println(".NET generation mode.");
+        generator = new DotnetGenerator(versionSet);
+        constants = new AmqpConstantSet(generator);
+        domainMap = new AmqpDomainMap(generator);
+        model = new AmqpModel(generator);       
+    	// TODO: Add templated that should be handled in here...
+       modelTemplateFiles = new File[]
+        {
+//          new File(tmplDir + Utils.fileSeparator + "XXXClass.tmpl"),
+        };
+        classTemplateFiles = new File[]
+        {
+//          new File(tmplDir + Utils.fileSeparator + "XXXClass.tmpl"),
+        };
+        methodTemplateFiles = new File[]
+        {
+//          new File(tmplDir + Utils.fileSeparator + "XXXClass.tmpl"),
+        };
+   }
+   
     private void prepareCpp()
     {
         if (tmplDir == null)
@@ -293,6 +331,7 @@
 		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("             -n:         Generate .NET.");
         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++;");