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*/
023package org.eigenbase.resgen;
024
025import org.apache.tools.ant.BuildException;
026
027import java.io.File;
028import java.io.PrintWriter;
029import java.io.StringWriter;
030import java.util.Arrays;
031import java.util.HashMap;
032import java.util.List;
033import 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 */
049public 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