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*/ 023package org.eigenbase.resgen; 024 025import java.io.File; 026import 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 */ 035class 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