001    /*
002    // $Id: //open/util/resgen/src/org/eigenbase/resgen/FileTask.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.*;
028    import java.util.Locale;
029    
030    /**
031     * Abstract base class for an Ant task which processes a file containing
032     * resources.
033     *
034     * @author jhyde
035     * @since 19 September, 2005
036     * @version $Id: //open/util/resgen/src/org/eigenbase/resgen/FileTask.java#4 $
037     */
038    abstract class FileTask 
039    {
040        ResourceGenTask.Include include;
041        String className;
042        String fileName;
043    
044        String cppClassName;
045    
046        boolean outputJava;
047        boolean outputCpp;
048    
049        abstract void process(ResourceGen generator) throws IOException;
050    
051        /**
052         * Returns the XML source file, e.g. happy/BirthdayResource_en.xml.
053         */
054        File getFile() {
055            return new File(include.root.src, fileName);
056        }
057    
058        /**
059         * Returns the XML source file, mangled for use in comments.
060         * e.g. .../BirthdayResource_en.xml if SCM-safe comments are enabled.
061         */
062        String getFileForComments()
063        {
064            String file = getFile().toString().replace('\\', '/');
065            
066            if (include.root.commentStyle == 
067                    ResourceGenTask.COMMENT_STYLE_SCM_SAFE) {
068                int slashPos = file.lastIndexOf('/');
069                if (slashPos > 0) {
070                    file = "..." + file.substring(slashPos);
071                }
072            }
073    
074            return file;
075        }
076    
077        boolean checkUpToDate(ResourceGen generator, File file) {
078            if (file.exists() &&
079                file.lastModified() >= getFile().lastModified()) {
080                generator.comment(file + " is up to date");
081                return true;
082            }
083    
084            return false;
085        }
086    
087        void makeParentDirs(File file)
088        {
089            if (file.getParentFile() != null) {
090                file.getParentFile().mkdirs();
091            }
092        }
093    
094        private String getPackageName()
095        {
096            int lastDot = className.lastIndexOf('.');
097            if (lastDot < 0) {
098                return null;
099            } else {
100                return className.substring(0, lastDot);
101            }
102        }
103    
104        private File getPackageDirectory(File file)
105        {
106            final String packageName = getPackageName();
107            if (packageName == null) {
108                return file;
109            }
110            return new File(file, packageName.replace('.', Util.fileSep));
111        }
112    
113        /**
114         * Returns the directory from which to read source files.
115         */
116        File getSrcDirectory()
117        {
118            return getPackageDirectory(include.root.src);
119        }
120    
121        /**
122         * Returns the directory to which to generate Java or C++ files.
123         */
124        File getDestDirectory()
125        {
126            return getPackageDirectory(include.root.dest);
127        }
128    
129    
130        /**
131         * Returns the directory to which to generate .properties and .xml
132         * files.
133         */
134        File getResourceDirectory()
135        {
136            return getPackageDirectory(include.root.res);
137        }
138    
139        /**
140         * Generates a Java class, e.g. com/foo/MyResource.java or
141         * com/foo/MyResource_en_US.java, depending upon whether locale is
142         * null.
143         */
144        void generateJava(
145                ResourceGen generator,
146                ResourceDef.ResourceBundle resourceList,
147                Locale locale) {
148            String fileName = Util.getClassNameSansPackage(className, locale) +
149                ".java";
150            File file = new File(getDestDirectory(), fileName);
151    
152            if (!include.root.force &&
153                checkUpToDate(generator, file)) {
154                return;
155            }
156    
157            generator.comment("Generating " + file);
158            final FileOutputStream out;
159            try {
160                makeParentDirs(file);
161    
162                out = new FileOutputStream(file);
163            } catch (FileNotFoundException e) {
164                throw new BuildException("Error while writing " + file, e);
165            }
166            PrintWriter pw = new PrintWriter(out);
167            try {
168                Generator gen;
169                if (locale == null) {
170                    String baseClassName = include.baseClassName;
171                    if (baseClassName == null) {
172                        baseClassName = "org.eigenbase.resgen.ShadowResourceBundle";
173                    }
174                    switch (include.root.style) {
175                    case ResourceGenTask.STYLE_DYNAMIC:
176                        gen = new JavaBaseGenerator(getFile(), file,
177                            className, baseClassName, resourceList);
178                        break;
179                    case ResourceGenTask.STYLE_FUNCTOR:
180                        gen = new JavaFunctorBaseGenerator(getFile(), file,
181                            className, baseClassName, resourceList);
182                        break;
183                    default:
184                        throw new AssertionError("unexpected style " +
185                            include.root.style);
186                    }
187                } else {
188                    // e.g. "mondrian.resource.MondrianResource_en_US"
189                    String className = this.className + "_" + locale.toString();
190                    // e.g. "mondrian.resource.MondrianResource"
191                    String baseClassName = this.className;
192                    gen = new JavaLocaleGenerator(getFile(), file, className,
193                        resourceList, locale, baseClassName);
194                }
195    
196                configureCommentStyle(gen);
197                
198                gen.generateModule(generator, resourceList, pw);
199            } finally {
200                pw.close();
201            }
202        }
203        
204        protected void configureCommentStyle(Generator gen)
205        {
206            switch(include.root.commentStyle) {
207            case ResourceGenTask.COMMENT_STYLE_NORMAL:
208                gen.setScmSafeComments(false);
209                break;
210    
211            case ResourceGenTask.COMMENT_STYLE_SCM_SAFE:
212                gen.setScmSafeComments(true);
213                break;
214    
215            default:
216                throw new AssertionError(
217                    "unexpected comment style " + include.root.commentStyle);
218            }
219    
220        }
221    }