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