1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 /* 24 * 25 /* 26 * XLIFFWriter.java 27 * 28 * 29 */ 30 31 package com.sun.star.tooling.converter; 32 33 import java.io.*; 34 import java.util.*; 35 36 import com.sun.star.tooling.DirtyTags.DirtyTagWrapper; 37 import com.sun.star.tooling.languageResolver.LanguageResolver; 38 import com.sun.star.tooling.languageResolver.LanguageResolver.LanguageResolvingException; 39 40 /** 41 * Write the Data to a wellformed XLIFF File 42 * 43 * @author Christian Schmidt 44 */ 45 public class XLIFFWriter extends DataWriter { 46 47 /** 48 * An array holding the keys of the HashMap containing the source language string 49 */ 50 private final static String[] sourceLineNames = { "Project", "SourceFile", 51 "Dummy", "ResType", "GID", "LID", "HID", "Platform", "Width", 52 "SourceLanguageID", "SourceText", "SourceHText", "SourceQText", 53 "SourceTitle", "TimeStamp" }; 54 /** 55 * An array holding the keys of the HashMap containing the target language string 56 */ 57 private final static String[] targetLineNames = { "Project", "SourceFile", 58 "Dummy", "ResType", "GID", "LID", "HID", "Platform", "Width", 59 "TargetLanguageID", "TargetText", "TargetHText", "TargetQText", 60 "TargetTitle", "TimeStamp" }; 61 /** 62 * An array holding the keys of the HashMap containing the source and target language string 63 */ 64 private final static String[] outLineNames = { "BlockNr", "Project", 65 "SourceFile", "Dummy", "ResType", "GID", "LID", "HID", "Platform", 66 "Width", "SourceLanguageID", "SourceText", "SourceHText", 67 "SourceQText", "SourceTitle", "TargetLanguageID", "TargetText", 68 "TargetHText", "TargetQText", "TargetTitle", "TimeStamp" }; 69 /** 70 * An Map holding the source and target content 71 */ 72 private final Map data = new ExtMap(outLineNames, null); 73 74 75 /** 76 * Indicates if this is the first Transunit to write 77 */ 78 boolean isFirst = true; 79 80 LanguageResolver languageResolver; 81 82 83 /** 84 * Create a new Instance of XLIFFWriter 85 * 86 * @param bos the Buffered Output Stream to write to 87 * @param charset the charset to use 88 * @throws IOException 89 */ XLIFFWriter(BufferedOutputStream bos, String charset)90 public XLIFFWriter(BufferedOutputStream bos, String charset) 91 throws IOException { 92 super(bos, charset); 93 this.languageResolver =new LanguageResolver(); 94 95 96 } 97 98 /* (non-Javadoc) 99 * @see com.sun.star.tooling.converter.DataWriter#getDatafrom(com.sun.star.tooling.converter.DataHandler) 100 */ getDatafrom(DataHandler handler)101 public void getDatafrom(DataHandler handler) throws java.io.IOException { 102 handler.putDataTo(this.data); 103 } 104 105 /** 106 * check if the item is an empty String 107 * 108 * @param item the string to check 109 * @return true if it is not empty, false if it is empty 110 */ isUsed(String item)111 private final boolean isUsed(String item) { 112 if (!"".equals(item)) 113 return true; 114 return false; 115 } 116 117 /** 118 * Replaces all characters that mustn't be in XLIFF PCdata 119 * 120 * @param string the string to check 121 * @return the checked string with all characters replaced 122 * @throws java.io.IOException 123 */ xmlString( final String string)124 private final String xmlString( final String string) throws java.io.IOException { 125 if (string == null) 126 return string; // "" 127 String str = string; 128 // str = str.replaceAll("&", "&"); 129 // str = str.replaceAll("<", "<"); 130 // str = str.replaceAll(">", ">"); 131 // str = str.replaceAll("\"", """); 132 // str = str.replaceAll("'", "'"); 133 for(int i=0;i<str.length();i++){ 134 if(str.charAt(i)=='&'){ 135 str=str.substring(0, i)+"&"+str.substring(i+1); 136 continue; 137 } 138 139 if(str.charAt(i)=='<'){ 140 str=str.substring(0, i)+"<"+str.substring(i+1); 141 continue; 142 } 143 144 if(str.charAt(i)=='>'){ 145 str=str.substring(0, i)+">"+str.substring(i+1); 146 continue; 147 } 148 149 if(str.charAt(i)=='"'){ 150 str=str.substring(0, i)+"""+str.substring(i+1); 151 continue; 152 } 153 154 if(str.charAt(i)=='\''){ 155 str=str.substring(0, i)+"'"+str.substring(i+1); 156 continue; 157 } 158 } 159 160 return str; 161 } 162 163 /* (non-Javadoc) 164 * @see java.io.Writer#close() 165 */ close()166 public void close() throws IOException { 167 this.writeTrailer(); 168 169 super.close(); 170 } 171 172 /* (non-Javadoc) 173 * @see com.sun.star.tooling.converter.DataWriter#writeData() 174 */ writeData()175 public void writeData() throws IOException { 176 if (isFirst) { 177 178 writeHeader(); 179 isFirst = false; 180 } 181 try{ 182 writeTransUnit(); 183 }catch(DirtyTagWrapper.TagWrapperException e){ 184 185 } 186 } 187 188 /** 189 * Write the XLIFFFiles header 190 * 191 * @throws IOException 192 */ writeHeader()193 private void writeHeader() throws IOException { 194 195 this.write(getHeader()); 196 } 197 198 /** 199 * Write the XLIFFFiles Trailer 200 * 201 * @throws IOException 202 */ writeTrailer()203 private void writeTrailer() throws IOException { 204 this.write(getTrailer()); 205 } 206 207 /** 208 * Write the next TransUnit 209 * 210 * @throws IOException 211 */ writeTransUnit()212 private void writeTransUnit() throws IOException, DirtyTagWrapper.TagWrapperException { 213 try{ 214 StringBuffer writeBuffer = new StringBuffer(1000); 215 216 StringBuffer allLinesEnd = new StringBuffer(200); 217 String sRessource = ""; 218 int parts = 0; 219 if (data == null) { 220 OutputHandler.out("error");// TBD Exception 221 } 222 223 if (!(this.data.get("SourceText").equals("") || this.data.get( 224 "SourceText").equals(" "))) { 225 parts++; 226 } 227 // if(!(this.data.get("SourceHText").equals("")||this.data.get("SourceHText").equals(" 228 // "))){ 229 // parts++; 230 // } 231 if (!(this.data.get("SourceQText").equals("") || this.data.get( 232 "SourceQText").equals(" "))) { 233 parts++; 234 } 235 if (!(this.data.get("SourceTitle").equals("") || this.data.get( 236 "SourceTitle").equals(" "))) { 237 parts++; 238 } 239 if (!(this.data.get("SourceText").equals("") || this.data.get( 240 "SourceText").equals(" "))) { 241 sRessource = "res"; // normal TEXT source 242 243 allLinesEnd 244 .append("\t\t\t\t<context-group name=\"StarOffice Attributes\">\n"); 245 246 if (isUsed((String) this.data.get("ResType"))) 247 allLinesEnd 248 .append("\t\t\t\t\t<context context-type=\"DBType\">" 249 + xmlString((String) this.data.get("ResType")) 250 + "</context>\n"); 251 if (isUsed((String) this.data.get("Project"))) 252 allLinesEnd 253 .append("\t\t\t\t\t<context context-type=\"Project\">" 254 + xmlString((String) this.data.get("Project")) 255 + "</context>\n"); 256 if (isUsed((String) this.data.get("SourceFile"))) 257 allLinesEnd 258 .append("\t\t\t\t\t<context context-type=\"Filename\">" 259 + xmlString((String) this.data 260 .get("SourceFile")) + "</context>\n"); 261 if (isUsed((String) this.data.get("SourceHText"))) 262 allLinesEnd 263 .append("\t\t\t\t\t<context context-type=\"SourceHelpText\">" 264 + xmlString((String) this.data 265 .get("SourceHText")) + "</context>\n"); 266 if (isUsed((String) this.data.get("TargetHText"))) 267 allLinesEnd 268 .append("\t\t\t\t\t<context context-type=\"TargetHelpText\">" 269 + xmlString((String) this.data 270 .get("TargetHText")) + "</context>\n"); 271 if (isUsed((String) this.data.get("ResType"))) 272 allLinesEnd.append("\t\t\t\t\t<context context-type=\"Type\">" 273 + xmlString((String) this.data.get("ResType")) 274 + "</context>\n"); 275 if (isUsed((String) this.data.get("GID"))) 276 allLinesEnd.append("\t\t\t\t\t<context context-type=\"GID\">" 277 + xmlString((String) this.data.get("GID")) 278 + "</context>\n"); 279 if (isUsed((String) this.data.get("LID"))) 280 allLinesEnd.append("\t\t\t\t\t<context context-type=\"LID\">" 281 + xmlString((String) this.data.get("LID")) 282 + "</context>\n"); 283 if (isUsed((String) this.data.get("HID"))) 284 allLinesEnd.append("\t\t\t\t\t<context context-type=\"HID\">" 285 + xmlString((String) this.data.get("HID")) 286 + "</context>\n"); 287 if (isUsed((String) this.data.get("Platform"))) 288 allLinesEnd 289 .append("\t\t\t\t\t<context context-type=\"Platform\">" 290 + xmlString((String) this.data.get("Platform")) 291 + "</context>\n"); 292 if (isUsed((String) this.data.get("Width"))) 293 allLinesEnd.append("\t\t\t\t\t<context context-type=\"Width\">" 294 + xmlString((String) this.data.get("Width")) 295 + "</context>\n"); 296 allLinesEnd.append("\t\t\t\t</context-group>\n" 297 + "\t\t\t</trans-unit>\n"); 298 299 writeBuffer.append("\t\t\t<trans-unit id=\"" 300 + this.data.get("BlockNr") + ":" + parts + "\" restype=\"" 301 + sRessource + "\" translate=\"yes\">\n"); 302 if (isUsed((String) this.data.get("SourceText"))) 303 writeBuffer.append("\t\t\t\t<source xml:lang=\"" 304 + languageResolver.getRFCFromISO((String)this.data.get("SourceLanguageID")) + "\">" 305 + DirtyTagWrapper.wrapString((String) this.data.get("SourceText")) 306 + "</source>\n"); 307 308 if (isUsed((String) this.data.get("TargetText"))) 309 writeBuffer 310 .append("\t\t\t\t<target state=\"to_translate\" xml:lang=\"" 311 + languageResolver.getRFCFromISO((String)this.data.get("TargetLanguageID")) 312 + "\">" 313 +DirtyTagWrapper.wrapString((String) this.data 314 .get("TargetText")) + "</target>\n"); 315 writeBuffer.append(allLinesEnd); 316 Converter.countLine(); 317 318 } 319 // if(!(this.data.get("SourceHText").equals("")||this.data.get("SourceHText").equals(" 320 // "))){ 321 // sRessource="res-Help"; //Source is Help 322 // //sLineNumber=String.valueOf(iLineNumber);// 323 // writeBuffer.append("\t\t<trans-unit 324 // id=\""+this.data.get("BlockNr")+":"+parts+"\" 325 // restype=\""+sRessource+"\" translate=\"yes\">\n");//always translate 326 // if(isUsed((String)this.data.get("SourceHText"))) 327 // writeBuffer.append("\t\t\t<source 328 // xml:lang=\""+this.data.get("SourceLanguageID")+"\">"+xmlString((String)this.data.get("SourceHText"))+"</source>\n"); 329 // if(isUsed((String)this.data.get("TargetHText"))) 330 // writeBuffer.append("\t\t\t<target state=\"to_translate\" 331 // xml:lang=\""+this.data.get("TargetLanguageID")+"\">"+xmlString((String)this.data.get("TargetHText"))+"</target>\n"); 332 // writeBuffer.append(allLinesEnd); 333 // Converter.countLine(); 334 // } 335 336 if (!(this.data.get("SourceQText").equals("") || this.data.get( 337 "SourceQText").equals(" "))) { 338 sRessource = "res-QuickHelp"; // Source is OuickHelp 339 // sLineNumber=String.valueOf(iLineNumber);// 340 writeBuffer.append("\t\t\t<trans-unit id=\"" 341 + this.data.get("BlockNr") + ":" + parts + "\" restype=\"" 342 + sRessource + "\" translate=\"yes\">\n");// always translate 343 if (isUsed((String) this.data.get("SourceQText"))) 344 writeBuffer.append("\t\t\t\t<source xml:lang=\"" 345 + languageResolver.getRFCFromISO((String)this.data.get("SourceLanguageID")) + "\">" 346 + DirtyTagWrapper.wrapString((String) this.data.get("SourceQText")) 347 + "</source>\n"); 348 if (isUsed((String) this.data.get("TargetQText"))) 349 writeBuffer 350 .append("\t\t\t\t<target state=\"to_translate\" xml:lang=\"" 351 + languageResolver.getRFCFromISO((String)this.data.get("TargetLanguageID")) 352 + "\">" 353 + DirtyTagWrapper.wrapString((String) this.data 354 .get("TargetQText")) + "</target>\n"); 355 writeBuffer.append(allLinesEnd); 356 Converter.countLine(); 357 } 358 359 if (!(this.data.get("SourceTitle").equals("") || this.data.get( 360 "SourceTitle").equals(" "))) { 361 sRessource = "res-Title"; // Source is Title 362 363 writeBuffer.append("\t\t\t<trans-unit id=\"" 364 + this.data.get("BlockNr") + ":" + parts + "\" restype=\"" 365 + sRessource + "\" translate=\"yes\">\n");// always translate 366 if (isUsed((String) this.data.get("SourceTitle"))) 367 writeBuffer.append("\t\t\t\t<source xml:lang=\"" 368 + languageResolver.getRFCFromISO((String)this.data.get("SourceLanguageID")) + "\">" 369 + DirtyTagWrapper.wrapString((String) this.data.get("SourceTitle")) 370 + "</source>\n"); 371 if (isUsed((String) this.data.get("TargetTitle"))) 372 writeBuffer 373 .append("\t\t\t\t<target state=\"to_translate\" xml:lang=\"" 374 + languageResolver.getRFCFromISO((String)this.data.get("TargetLanguageID")) 375 + "\">" 376 + DirtyTagWrapper.wrapString((String) this.data 377 .get("TargetTitle")) + "</target>\n"); 378 writeBuffer.append(allLinesEnd); 379 Converter.countLine(); 380 } 381 this.write(writeBuffer.toString()); 382 }catch(Exception e){ 383 OutputHandler.log(e.getMessage()); 384 } 385 } 386 387 /** 388 * Create the XLIFFFiles Header 389 * 390 * @return the header as string 391 * @throws java.io.UnsupportedEncodingException 392 */ getHeader()393 private String getHeader() throws java.io.UnsupportedEncodingException { 394 return new String( 395 (getProcessingInstructionTag() + getDTDLine() 396 + openVersionLine() + openFileLine() + getHeaderTag() + openBodyTag()) 397 .getBytes(), "UTF8"); 398 399 } 400 401 /** 402 * Create the XLIFFFiles Trailer 403 * 404 * @return the trailer as string 405 */ getTrailer()406 private String getTrailer() { 407 return closeBodyTag() + closeFileLine() + closeVersionLine(); 408 } 409 410 /** 411 * Create the Processing Instruction Tag used by this XLIFFFile 412 * @return the Processing Instruction Tag used by this XLIFFFile 413 */ getProcessingInstructionTag()414 private String getProcessingInstructionTag() { 415 String sPITagStart = "<?"; 416 String sPIName = "xml "; 417 String sPIVersion = "version=\"1.0\" "; 418 String sPIEncoding = "encoding=\"UTF-8\""; 419 String sPITagEnd = "?>"; 420 return sPITagStart + sPIName + sPIVersion + sPIEncoding 421 + /* sPIStandalone+ */sPITagEnd + '\n'; 422 } 423 424 /** 425 * Create the line holding the DTD referenced by this XLIFFFile 426 * @return a string holding the DTD referenced by this XLIFFFile 427 */ getDTDLine()428 private String getDTDLine() { 429 String sDTDTagStart = "<!DOCTYPE "; 430 String sDTDType = "xliff "; 431 String sDTDSource = "PUBLIC \"-//XLIFF//DTD XLIFF//EN\" \"http://www.oasis-open.org/committees/xliff/documents/xliff.dtd\">";// http://www.oasis-open.org/committees/xliff/documents/ 432 String sDTSTagEnd = ">"; 433 return sDTDTagStart + sDTDType + sDTDSource + '\n'; 434 } 435 436 /** 437 * Create the beginning of the line holding the version of this XIFFFile 438 * 439 * @return a string with the beginning of the line holding the version of this XIFFFile 440 */ openVersionLine()441 private String openVersionLine() { 442 return "<xliff version=\"1.0\">\n"; 443 } 444 /** 445 * Create the ending of the line holding the version of this XIFFFile 446 * 447 * @return a string with the ending of the line holding the version of this XIFFFile 448 */ closeVersionLine()449 private String closeVersionLine() { 450 return "</xliff>"; 451 } 452 /** 453 * Create the beginning of the line holding the file tag of this XIFFFile 454 * 455 * @return a string with the beginning of the file tag of this XIFFFile 456 */ openFileLine()457 private String openFileLine() { 458 459 String FileTagStart = "\t<file"; 460 String FileDataType = " datatype=\"STAROFFICE\""; 461 String FileDate = " date=\"" + this.data.get("TimeStamp") + "\""; 462 String FileOriginal = " original=\"" + this.data.get("SourceFile") 463 + "\""; 464 String FileSourceLanguage=""; 465 String FileTargetLanguage=""; 466 try { 467 FileSourceLanguage = " source-language=\"" 468 + languageResolver.getRFCFromISO((String)this.data.get("SourceLanguageID")) + "\" "; 469 FileTargetLanguage = " target-language=\"" 470 + languageResolver.getRFCFromISO((String)this.data.get("TargetLanguageID")) + "\" "; 471 } catch (LanguageResolvingException e) { 472 OutputHandler.out(e.getMessage()); 473 } 474 String FileTagEnd = ">"; 475 return FileTagStart + FileDataType + FileDate + FileOriginal 476 + FileSourceLanguage + FileTargetLanguage + FileTagEnd; 477 478 } 479 /** 480 * Create the ending of the line holding the file tag of this XIFFFile 481 * 482 * @return a string with the ending of the file tag of this XIFFFile 483 */ closeFileLine()484 private String closeFileLine() { 485 return "\t</file>"; 486 } 487 /** 488 * Create a String containing the header tag 489 * @return the String containing the header tag 490 */ getHeaderTag()491 private String getHeaderTag() { 492 return "<header></header>\n"; 493 } 494 /** 495 * Create the begining of the line holding the body tag of this XIFFFile 496 * 497 * @return a string with the begining of the body tag of this XIFFFile 498 */ openBodyTag()499 private String openBodyTag() { 500 return "\t\t<body>\n"; 501 } 502 /** 503 * Create the ending of the line holding the body tag of this XIFFFile 504 * 505 * @return a string with the ending of the body tag of this XIFFFile 506 */ closeBodyTag()507 private String closeBodyTag() { 508 return "\t\t</body>"; 509 } 510 511 /* 512 * (non-Javadoc) 513 * 514 * @see com.sun.star.tooling.converter.DataWriter#writeData(java.util.Map[]) 515 */ writeData(Map[] data)516 protected void writeData(Map[] data) throws IOException { 517 // TODO Auto-generated method stub 518 519 } 520 521 /* 522 * (non-Javadoc) 523 * 524 * @see com.sun.star.tooling.converter.DataWriter#getDataFrom(com.sun.star.tooling.converter.DataHandler) 525 */ getDataFrom(DataHandler handler)526 protected void getDataFrom(DataHandler handler) { } 527 528 } 529