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*/
023package org.eigenbase.resgen;
024
025import org.apache.tools.ant.BuildException;
026
027import java.io.*;
028import 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 */
038abstract 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}