001 /*
002 // $Id: //open/util/resgen/src/org/eigenbase/resgen/CppGenerator.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.File;
026 import java.io.PrintWriter;
027
028 /**
029 * Generates a C++ class containing resource definitions.
030 *
031 * @author jhyde
032 * @since 19 September, 2005
033 * @version $Id: //open/util/resgen/src/org/eigenbase/resgen/CppGenerator.java#3 $
034 */
035 class CppGenerator extends AbstractGenerator
036 {
037 private final String className;
038 private final String defaultExceptionClassName;
039 private final String headerFilename;
040 private final String baseClassName;
041
042 private static final String CPP_STRING = "const std::string &";
043 private static final String CPP_NUMBER = "int";
044 private static final String CPP_DATE_TIME = "time_t";
045 private static final String[] CPP_TYPE_NAMES =
046 {CPP_STRING, CPP_NUMBER, CPP_DATE_TIME, CPP_DATE_TIME};
047
048 /**
049 * Creates a C++ header generator.
050 *
051 * @param srcFile
052 * @param file
053 * @param className
054 * @param baseClassName Name of base class, must not be null, typically
055 * @param defaultExceptionClassName
056 */
057 CppGenerator(
058 File srcFile,
059 File file,
060 String className,
061 String baseClassName,
062 String defaultExceptionClassName,
063 String headerFilename)
064 {
065 super(srcFile, file);
066 assert className.indexOf('.') < 0 :
067 "C++ class name must not contain '.': " + className;
068 this.className = className;
069 this.defaultExceptionClassName = defaultExceptionClassName;
070 this.headerFilename = headerFilename;
071 assert baseClassName != null;
072 this.baseClassName = baseClassName;
073 }
074
075 protected String getClassName()
076 {
077 return className;
078 }
079
080 protected String getBaseClassName()
081 {
082 return baseClassName;
083 }
084
085 protected String[] getArgTypes(String message) {
086 return ResourceDefinition.getArgTypes(message, CPP_TYPE_NAMES);
087 }
088
089 public void generateModule(ResourceGen generator, ResourceDef.ResourceBundle resourceList, PrintWriter pw)
090 {
091 generateDoNotModifyHeader(pw);
092 generateGeneratedByBlock(pw);
093
094 String className = getClassName();
095 String bundleCacheClassName = className + "BundleCache";
096 String baseClass = getBaseClassName();
097
098 if (resourceList.cppCommonInclude != null) {
099 pw.println(
100 "// begin common include specified by "
101 + getSrcFileForComment());
102 pw.println("#include \"" + resourceList.cppCommonInclude + "\"");
103 pw.println(
104 "// end common include specified by "
105 + getSrcFileForComment());
106 }
107
108 pw.println("#include \"" + headerFilename + "\"");
109 pw.println("#include \"ResourceBundle.h\"");
110 pw.println("#include \"Locale.h\"");
111 pw.println();
112 pw.println("#include <map>");
113 pw.println("#include <string>");
114 pw.println();
115
116 if (resourceList.cppNamespace != null) {
117 pw.println("namespace " + resourceList.cppNamespace + " {");
118 pw.println();
119 }
120
121 pw.println("using namespace std;");
122 pw.println();
123 pw.println("#define BASENAME (\"" + className + "\")");
124 pw.println();
125 pw.println("static " + bundleCacheClassName + " bundleCache;");
126 pw.println("static string bundleLocation(\"\");");
127 pw.println();
128
129 pw.println("const " + className + " &" + className + "::instance()");
130 pw.println("{");
131 pw.println(" return " + className + "::instance(Locale::getDefault());");
132 pw.println("}");
133 pw.println();
134 pw.println("const " + className
135 + " &" + className + "::instance(const Locale &locale)");
136 pw.println("{");
137 pw.println(" return *makeInstance<"
138 + className + ", "
139 + bundleCacheClassName + ", "
140 + bundleCacheClassName
141 + "::iterator>(bundleCache, locale);");
142 pw.println("}");
143 pw.println();
144 pw.println("void "
145 + className
146 + "::setResourceFileLocation(const string &location)");
147 pw.println("{");
148 pw.println(" bundleLocation = location;");
149 pw.println("}");
150 pw.println();
151
152 pw.println("" + className + "::" + className + "(Locale locale)");
153 pw.println(" : " + baseClass
154 + "(BASENAME, locale, bundleLocation),");
155
156 for(int i = 0; i < resourceList.resources.length; i++) {
157 ResourceDef.Resource resource = resourceList.resources[i];
158
159 pw.print(" _"
160 + resource.name
161 + "(this, \""
162 + resource.name
163 + "\")");
164
165 if (i + 1 < resourceList.resources.length) {
166 pw.println(',');
167 } else {
168 pw.println();
169 }
170 }
171 pw.println("{ }");
172 pw.println();
173
174 for (int i = 0; i < resourceList.resources.length; i++) {
175 generateResource(resourceList.resources[i], pw);
176 }
177
178 if (resourceList.cppNamespace != null) {
179 pw.println();
180 pw.println("} // end namespace " + resourceList.cppNamespace);
181 }
182 }
183
184 public void generateResource(
185 ResourceDef.Resource resource,
186 PrintWriter pw)
187 {
188 String text = resource.text.cdata;
189 //String comment = ResourceGen.getComment(resource);
190
191 // e.g. "Internal"
192 final String resourceInitCap =
193 ResourceGen.getResourceInitcap(resource);
194
195 String parameterList = getParameterList(text);
196 String argumentList = getArgumentList(text);
197
198 pw.println("string " + className + "::" + resource.name + "("
199 + parameterList + ") const");
200 pw.println("{");
201 pw.println(" return _"
202 + resource.name
203 + ".format("
204 + argumentList
205 + ");");
206 pw.println("}");
207
208 if (resource instanceof ResourceDef.Exception) {
209 ResourceDef.Exception exception =
210 (ResourceDef.Exception)resource;
211
212 String exceptionClass = exception.cppClassName;
213 if (exceptionClass == null) {
214 exceptionClass = defaultExceptionClassName;
215 }
216
217 pw.println(exceptionClass + "* "
218 + className + "::new" + resourceInitCap + "("
219 + parameterList + ") const");
220 pw.println("{");
221 pw.println(" return new "
222 + exceptionClass
223 + "("
224 + resource.name
225 + "("
226 + argumentList
227 + "));");
228 pw.println("}");
229 pw.println();
230
231 boolean chainExceptions =
232 (exception.cppChainExceptions != null &&
233 exception.cppChainExceptions.equalsIgnoreCase("true"));
234
235 if (chainExceptions) {
236 if (parameterList.length() > 0) {
237 pw.println(exceptionClass
238 + "* "
239 + className
240 + "::new"
241 + resourceInitCap
242 + "("
243 + parameterList
244 + ", const "
245 + exceptionClass
246 + " * const prev) const");
247 } else {
248 pw.println(exceptionClass
249 + " "
250 + className
251 + "::new"
252 + resourceInitCap
253 + "(const "
254 + exceptionClass
255 + " * const prev) const");
256 }
257 pw.println("{");
258
259 pw.println(" return new "
260 + exceptionClass
261 + "("
262 + resource.name
263 + "("
264 + argumentList
265 + "), prev);");
266 pw.println("}");
267 pw.println();
268 }
269 }
270 }
271 }
272
273 // End CppGenerator.java