001 /*
002 // $Id: //open/util/resgen/src/org/eigenbase/resgen/JavaFunctorBaseGenerator.java#4 $
003 // Package org.eigenbase.resgen is an i18n resource generator.
004 // Copyright (C) 2005-2005 The Eigenbase Project
005 // Copyright (C) 2005-2005 Disruptive Tech
006 // Copyright (C) 2005-2005 LucidEra, Inc.
007 // Portions Copyright (C) 2001-2005 Kana Software, Inc. and others.
008 //
009 // This library is free software; you can redistribute it and/or modify it
010 // under the terms of the GNU Lesser General Public License as published by the
011 // Free Software Foundation; either version 2 of the License, or (at your
012 // option) any later version approved by The Eigenbase Project.
013 //
014 // This library is distributed in the hope that it will be useful,
015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
017 // GNU Lesser General Public License for more details.
018 //
019 // You should have received a copy of the GNU Lesser General Public License
020 // along with this library; if not, write to the Free Software
021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022 */
023 package org.eigenbase.resgen;
024
025 import org.apache.tools.ant.BuildException;
026
027 import java.io.File;
028 import java.io.PrintWriter;
029 import java.io.StringWriter;
030 import java.util.Arrays;
031 import java.util.HashMap;
032 import java.util.List;
033 import java.util.Map;
034
035 /**
036 * Generates a Java class for the base locale,
037 * using the 'functor' code-generation style.
038 *
039 * <p>For each resource, the generated Java class contains one public, final,
040 * non-static member. This member belongs to a class which has a number of
041 * methods for creating strings or exceptions based upon this resource. The
042 * methods are typesafe; that is, they have the same number and type of
043 * parameters as the resource itself.
044 *
045 * @author jhyde
046 * @since 19 September, 2005
047 * @version $Id: //open/util/resgen/src/org/eigenbase/resgen/JavaFunctorBaseGenerator.java#4 $
048 */
049 public class JavaFunctorBaseGenerator extends JavaBaseGenerator
050 {
051 private final Map functorMap = new HashMap();
052 private final StringWriter functorSw = new StringWriter();
053 private final PrintWriter functorPw = new PrintWriter(functorSw);
054
055 JavaFunctorBaseGenerator(
056 File srcFile,
057 File file,
058 String className,
059 String baseClassName,
060 ResourceDef.ResourceBundle resourceBundle)
061 {
062 super(srcFile, file, className, baseClassName, resourceBundle);
063 }
064
065 public void generateResource(ResourceDef.Resource resource, PrintWriter pw) {
066 if (resource.text == null) {
067 throw new BuildException(
068 "Resource '" + resource.name + "' has no message");
069 }
070 String text = resource.text.cdata;
071 String comment = ResourceGen.getComment(resource);
072 final String resourceInitcap = ResourceGen.getResourceInitcap(resource);// e.g. "Internal"
073
074 String parameterList = getParameterList(text);
075 String argumentList = getArgumentList(text);
076 String propList = getPropList(resource);
077 String errorClassName;
078 if (resource instanceof ResourceDef.Exception) {
079 ResourceDef.Exception exception = (ResourceDef.Exception) resource;
080 errorClassName = getErrorClass(exception);
081 } else {
082 errorClassName = null;
083 }
084 String functorType =
085 getFunctorType(parameterList, argumentList, errorClassName);
086
087 pw.println();
088 Util.generateCommentBlock(pw, resource.name, text, comment);
089 pw.println(" public final " + functorType + " " + resourceInitcap + " = new " + functorType + "(" + Util.quoteForJava(resourceInitcap) + ", " + Util.quoteForJava(text) + ", " + propList + ");");
090 }
091
092 private String getPropList(ResourceDef.Resource resource) {
093 if (resource.properties == null || resource.properties.length == 0) {
094 return "null";
095 }
096 final StringBuffer buf = new StringBuffer("new String[] {");
097 for (int i = 0; i < resource.properties.length; i++) {
098 if (i > 0) {
099 buf.append(", ");
100 }
101 ResourceDef.Property property = resource.properties[i];
102 buf.append(Util.quoteForJava(property.name));
103 buf.append(", ");
104 buf.append(Util.quoteForJava(property.cdata));
105 }
106 buf.append("}");
107 return buf.toString();
108 }
109
110 private String getFunctorType(
111 String parameterList,
112 String argumentList,
113 String errorClassName)
114 {
115 List key = Arrays.asList(new String[] {parameterList, errorClassName});
116 String functorType = (String) functorMap.get(key);
117 if (functorType == null) {
118 functorType = "_Def" + functorMap.size();
119 functorMap.put(key, functorType);
120 genFunctor(functorType, parameterList, argumentList, errorClassName, functorPw);
121 }
122
123 return functorType;
124 }
125
126 private void genFunctor(String functorType, String parameterList, String argumentList, String errorClassName, PrintWriter pw) {
127 String definitionClass = "org.eigenbase.resgen.ResourceDefinition";
128 final String classNameSansPackage = Util.removePackage(className);
129 final String bundleThis = classNameSansPackage + ".this";
130 String argumentArray = argumentList.equals("") ?
131 "emptyObjectArray" :
132 "new Object[] {" + argumentList + "}";
133 pw.println();
134 pw.println(" /**");
135 pw.println(" * Definition for resources which");
136 if (errorClassName != null) {
137 pw.println(" * return a {@link " + errorClassName + "} exception and");
138 }
139 pw.println(" * take arguments '" + parameterList + "'.");
140 pw.println(" */");
141 pw.println(" public final class " + functorType + " extends " + definitionClass + " {");
142 pw.println(" " + functorType + "(String key, String baseMessage, String[] props) {");
143 pw.println(" super(key, baseMessage, props);");
144 pw.println(" }");
145 pw.println(" public String str(" + parameterList + ") {");
146 pw.println(" return instantiate(" + addLists(bundleThis, argumentArray) + ").toString();");
147 pw.println(" }");
148 if (errorClassName != null) {
149 final ExceptionDescription ed = new ExceptionDescription(errorClassName);
150 if (ed.hasInstCon) {
151 pw.println(" public " + errorClassName + " ex(" + parameterList + ") {");
152 pw.println(" return new " + errorClassName + "(instantiate(" + addLists(bundleThis, argumentArray) + "));");
153 pw.println(" }");
154 } else if (ed.hasInstThrowCon) {
155 pw.println(" public " + errorClassName + " ex(" + parameterList + ") {");
156 pw.println(" return new " + errorClassName + "(instantiate(" + addLists(bundleThis, argumentArray) + "), null);");
157 pw.println(" }");
158 } else if (ed.hasStringCon) {
159 pw.println(" public " + errorClassName + " ex(" + parameterList + ") {");
160 pw.println(" return new " + errorClassName + "(instantiate(" + addLists(bundleThis, argumentArray) + ").toString());");
161 pw.println(" }");
162 } else if (ed.hasStringThrowCon) {
163 pw.println(" public " + errorClassName + " ex(" + parameterList + ") {");
164 pw.println(" return new " + errorClassName + "(instantiate(" + addLists(bundleThis, argumentArray) + ").toString(), null);");
165 pw.println(" }");
166 }
167 if (ed.hasInstThrowCon) {
168 pw.println(" public " + errorClassName + " ex(" + addLists(parameterList, "Throwable err") + ") {");
169 pw.println(" return new " + errorClassName + "(instantiate(" + addLists(bundleThis, argumentArray) + "), err);");
170 pw.println(" }");
171 } else if (ed.hasStringThrowCon) {
172 pw.println(" public " + errorClassName + " ex(" + addLists(parameterList, "Throwable err") + ") {");
173 pw.println(" return new " + errorClassName + "(instantiate(" + addLists(bundleThis, argumentArray) + ").toString(), err);");
174 pw.println(" }");
175 }
176 }
177 pw.println(" }");
178 }
179
180 protected void postModule(PrintWriter pw) {
181 functorPw.flush();
182 pw.println(functorSw.toString());
183 }
184 }
185
186 // End JavaFunctorBaseGenerator.java