001    /*
002    // $Id: //open/util/resgen/src/org/eigenbase/resgen/AbstractGenerator.java#3 $
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 java.io.PrintWriter;
026    import java.io.File;
027    import java.util.Date;
028    import java.text.Format;
029    import java.text.MessageFormat;
030    import java.text.NumberFormat;
031    import java.text.DateFormat;
032    import java.lang.reflect.Method;
033    import java.lang.reflect.InvocationTargetException;
034    
035    /**
036     * Abstract base for all generators.
037     *
038     * @author jhyde
039     * @since 19 September, 2005
040     * @version $Id: //open/util/resgen/src/org/eigenbase/resgen/AbstractGenerator.java#3 $
041     */
042    abstract class AbstractGenerator implements Generator
043    {
044        private final File srcFile;
045        private final File file;
046        private Boolean scmSafeComments = null;
047    
048        public AbstractGenerator(File srcFile, File file)
049        {
050            this.srcFile = srcFile;
051            this.file = file;
052        }
053    
054        public void setScmSafeComments(boolean enabled)
055        {
056            if (scmSafeComments != null) {
057                throw new AssertionError(
058                    "SCM safe comment style may only be configured once.");
059            }
060    
061            scmSafeComments = enabled ? Boolean.TRUE : Boolean.FALSE;
062        }
063    
064        protected boolean useScmSafeComments()
065        {
066            return scmSafeComments != null && scmSafeComments.booleanValue();
067        }
068    
069        /**
070         * Generates code for a particular resource.
071         */
072        protected abstract void generateResource(
073            ResourceDef.Resource resource,
074            PrintWriter pw);
075    
076        protected void generateDoNotModifyHeader(PrintWriter pw) {
077            if (useScmSafeComments()) {
078                pw.println(
079                    "// This class is generated. Do NOT modify it manually.");
080            } else {
081                pw.println("// This class is generated. Do NOT modify it, or");
082                pw.println("// add it to source control.");
083            }
084            pw.println();
085        }
086    
087        protected void generateGeneratedByBlock(PrintWriter pw) {
088            pw.println("/**");
089            pw.println(" * This class was generated");
090            pw.println(" * by " + ResourceGen.class);
091    
092            String file = getSrcFileForComment();
093            pw.println(" * from " + file);
094            if (!useScmSafeComments()) {
095                pw.println(" * on " + new Date().toString() + ".");
096            }
097            pw.println(" * It contains a list of messages, and methods to");
098            pw.println(" * retrieve and format those messages.");
099            pw.println(" */");
100            pw.println();
101        }
102    
103        /**
104         * Returns the generator's output file.  e.g., "BirthdayResource.java"
105         */
106        protected File getFile()
107        {
108            return file;
109        }
110    
111        /**
112         * Returns the XML or .properties source file, in a manner suitable
113         * for use in source code comments.  Path information is stripped if
114         * SCM-safe comment style is enabled.
115         * 
116         * @see #setScmSafeComments(boolean)
117         */
118        protected String getSrcFileForComment()
119        {
120            String filename = srcFile.toString().replace('\\', '/');
121            
122            if (useScmSafeComments()) {
123                int slashPos = filename.lastIndexOf('/');
124                if (slashPos > 0) {
125                    filename = "..." + filename.substring(slashPos);
126                }
127            }
128            
129            return filename;
130        }
131        
132        /**
133         * Returns the fully-qualified name of the class being generated,
134         * for example "happy.BirthdayResource_en_US".
135         */
136        protected abstract String getClassName();
137    
138        /**
139         * Returns the fully-qualified name of the base class.
140         */
141        protected abstract String getBaseClassName();
142    
143        /**
144         * Returns a parameter list string, e.g. "String p0, int p1".
145         */
146        protected String getParameterList(String message) {
147            final String [] types = getArgTypes(message);
148            if (types.length == 0) {
149                return "";
150            }
151            StringBuffer sb = new StringBuffer();
152            for (int i = 0; i < types.length; i++) {
153                String type = types[i];
154                if (i > 0) {
155                    sb.append(", ");
156                }
157                sb.append(type);
158    
159                // If this is a C++ pointer type, say "const char *", don't put
160                // a space between it and the variable name.
161                if (!type.endsWith("&") && !type.endsWith("*")) {
162                    sb.append(" ");
163                }
164                sb.append("p");
165                sb.append(Integer.toString(i));
166            }
167            return sb.toString();
168        }
169    
170        /**
171         * Returns the number and types of parameters in the given error message,
172         * expressed as an array of Strings (legal values are
173         * currently "String", "Number", "java.util.Date", and null) ordered by
174         * parameter number.
175         */
176        protected abstract String [] getArgTypes(String message);
177    
178        protected String getArgumentList(String message)
179        {
180            final String [] types = getArgTypes(message);
181    
182            if (types.length == 0) {
183                return "";
184            }
185    
186            StringBuffer sb = new StringBuffer();
187            for (int i = 0; i < types.length; i++) {
188                if (i > 0) {
189                    sb.append(", ");
190                }
191                sb.append("p");
192                sb.append(Integer.toString(i));
193            }
194            return sb.toString();
195        }
196    
197    }
198    
199    // End AbstractGenerator.java