• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *****************************************************************************
3  * Copyright (C) 2000-2004, International Business Machines Corporation and  *
4  * others. All Rights Reserved.                                              *
5  *****************************************************************************
6  */
7 package com.ibm.rbm;
8 
9 import java.io.*;
10 import java.util.*;
11 import java.text.*;
12 
13 import javax.swing.*;
14 import javax.xml.parsers.*;
15 import javax.xml.transform.*;
16 import javax.xml.transform.dom.*;
17 import javax.xml.transform.stream.*;
18 
19 import org.w3c.dom.*;
20 
21 /**
22  * This class is a plug-in to RBManager that allows the user to export Resource Bundles
23  * along with some of the meta-data associated by RBManager to the XLIFF specification.
24  * For more information on XLIFF visit the web site
25  * <a href="http://www.lisa.org/xliff/">http://www.lisa.org/xliff/</a>
26  *
27  * @author George Rhoten
28  * @see com.ibm.rbm.RBManager
29  */
30 public class RBxliffExporter extends RBExporter {
31     private static final String VERSION = "0.7";
32     private static final String XLIFF_DTD = "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd";
33     private static final String XLIFF_PUBLIC_NAME = "-//XLIFF//DTD XLIFF//EN";
34     private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
35 
36     /**
37      * Default constructor for the XLIFF exporter.
38      */
39 
RBxliffExporter()40     public RBxliffExporter() {
41         super();
42 
43         // Initialize the file chooser if necessary
44         if (chooser == null) {
45             chooser = new JFileChooser();
46             chooser.setFileFilter(new javax.swing.filechooser.FileFilter(){
47                 public String getDescription() {
48                     return "XLIFF Files";
49                 }
50                 public boolean accept(File f) {
51                     return (f.isDirectory() || f.getName().endsWith(".xlf"));
52                 }
53             });
54         }
55     }
56 
convertToISO(Date d)57     private String convertToISO(Date d) {
58         GregorianCalendar gc = new GregorianCalendar();
59         gc.setTime(d);
60         return convertToISO(gc);
61     }
62 
convertToISO(GregorianCalendar gc)63     private String convertToISO(GregorianCalendar gc) {
64     	dateFormat.setCalendar(gc);
65         return dateFormat.format(gc.getTime());
66     }
67 
getLocale(Bundle item)68     private String getLocale(Bundle item) {
69         String language = item.getLanguageEncoding();
70         if (language != null && !language.equals("")) {
71             //language = language.toUpperCase();
72             String country = item.getCountryEncoding();
73             if (country != null && !country.equals("")) {
74                 //country = country.toUpperCase();
75                 String variant = item.getVariantEncoding();
76                 if (variant != null && !variant.equals("")) {
77                     //variant = variant.toUpperCase();
78                     return language + "-" + country + "-" + variant;
79                 }
80                 return language + "-" + country;
81             }
82             return language;
83         }
84         return "";
85     }
86 
getParentLocale(String locale)87     private String getParentLocale(String locale) {
88 
89     	int truncIndex = locale.lastIndexOf('-');
90     	if (truncIndex > 0) {
91     		locale = locale.substring(0, truncIndex);
92     	}
93     	else {
94     		locale = "";
95     	}
96     	return locale;
97     }
98 
addTransUnit(Document xml, Element groupElem, BundleItem item, BundleItem parent_item)99     private void addTransUnit(Document xml, Element groupElem, BundleItem item, BundleItem parent_item) {
100         Element transUnit = xml.createElement("trans-unit");
101         transUnit.setAttribute("date",convertToISO(item.getModifiedDate()));
102         transUnit.setAttribute("id",item.getKey());
103 
104         String sourceOrTarget = "target";
105         if (parent_item == null) {
106         	sourceOrTarget = "source";
107         }
108         else {
109             Element source = xml.createElement("source");
110             source.setAttribute("xml:space","preserve");
111             source.appendChild(xml.createTextNode(parent_item.getTranslation()));
112             transUnit.appendChild(source);
113         }
114         Element target = xml.createElement(sourceOrTarget);
115         target.setAttribute("xml:space","preserve");
116     	// This is different from the translate attribute
117         if (item.isTranslated()) {
118         	// TODO Handle the other states in the future.
119         	transUnit.setAttribute("state", "translated");
120         }
121         target.appendChild(xml.createTextNode(item.getTranslation()));
122         transUnit.appendChild(target);
123 
124         if (item.getComment() != null && item.getComment().length() > 1) {
125 	        Element comment_prop = xml.createElement("note");
126 	        comment_prop.setAttribute("xml:space","preserve");
127 	        comment_prop.appendChild(xml.createTextNode(item.getComment()));
128 	        transUnit.appendChild(comment_prop);
129         }
130 
131         if ((item.getCreator() != null && item.getCreator().length() > 1)
132         	|| (item.getModifier() != null && item.getModifier().length() > 1))
133         {
134             Element transUnit_prop_group_elem = xml.createElement("prop-group");
135 
136             if (item.getCreator() != null && item.getCreator().length() > 1) {
137 	            Element creator_prop = xml.createElement("prop");
138 	            creator_prop.setAttribute("prop-type","creator");
139 	            creator_prop.appendChild(xml.createTextNode(item.getCreator()));
140 		        transUnit_prop_group_elem.appendChild(creator_prop);
141             }
142 
143             if (item.getCreator() != null && item.getCreator().length() > 1) {
144 	            Element created_prop = xml.createElement("prop");
145 	            created_prop.setAttribute("prop-type","created");
146 	            created_prop.appendChild(xml.createTextNode(convertToISO(item.getCreatedDate())));
147 		        transUnit_prop_group_elem.appendChild(created_prop);
148             }
149 
150         	if (item.getModifier() != null && item.getModifier().length() > 1) {
151 		        Element modifier_prop = xml.createElement("prop");
152 		        modifier_prop.setAttribute("prop-type","modifier");
153 		        modifier_prop.appendChild(xml.createTextNode(item.getModifier()));
154 		        transUnit_prop_group_elem.appendChild(modifier_prop);
155         	}
156 
157 	        transUnit.appendChild(transUnit_prop_group_elem);
158         }
159 
160         groupElem.appendChild(transUnit);
161     }
162 
export(RBManager rbm)163     public void export(RBManager rbm) throws IOException {
164         if (rbm == null)
165         	return;
166         // Open the Save Dialog
167         int ret_val = chooser.showSaveDialog(null);
168         if (ret_val != JFileChooser.APPROVE_OPTION)
169         	return;
170         // Retrieve basic file information
171         File file = chooser.getSelectedFile();              // The file(s) we will be working with
172         File directory = new File(file.getParent());        // The directory we will be writing to
173         String base_name = file.getName();                  // The base name of the files we will write
174         if (base_name == null || base_name.equals(""))
175         	base_name = rbm.getBaseClass();
176         if (base_name.endsWith(".xlf"))
177         	base_name = base_name.substring(0,base_name.length()-4);
178 
179         String file_name = base_name + ".xlf";
180 
181         Vector bundle_v = rbm.getBundles();
182         Enumeration bundleIter = bundle_v.elements();
183         while (bundleIter.hasMoreElements()) {
184         	exportFile(rbm, directory, base_name, (Bundle)bundleIter.nextElement());
185         }
186     }
187 
addHeaderProperties(Document xml, Element header, Bundle main_bundle)188     private void addHeaderProperties(Document xml, Element header, Bundle main_bundle) {
189         if (main_bundle.comment != null && main_bundle.comment.length() > 0) {
190             Element note = xml.createElement("note");
191         	header.appendChild(note);
192             note.appendChild(xml.createTextNode(main_bundle.comment));
193             note.setAttribute("xml:space","preserve");
194         }
195         if ((main_bundle.name != null && main_bundle.name.length() > 0)
196     		|| (main_bundle.manager != null && main_bundle.manager.length() > 0)
197         	|| (main_bundle.language != null && main_bundle.language.length() > 0)
198 			|| (main_bundle.country != null && main_bundle.country.length() > 0)
199 			|| (main_bundle.variant != null && main_bundle.variant.length() > 0))
200         {
201             Element prop_group = xml.createElement("prop-group");
202         	header.appendChild(prop_group);
203             if (main_bundle.name != null && main_bundle.name.length() > 0) {
204                 Element prop = xml.createElement("prop");
205             	header.appendChild(prop);
206             	prop.setAttribute("xml:space","preserve");
207             	prop.setAttribute("prop-type","name");
208             	prop.appendChild(xml.createTextNode(main_bundle.name));
209             	prop_group.appendChild(prop);
210             }
211             if (main_bundle.manager != null && main_bundle.manager.length() > 0) {
212                 Element prop = xml.createElement("prop");
213             	header.appendChild(prop);
214             	prop.setAttribute("xml:space","preserve");
215             	prop.setAttribute("prop-type","manager");
216             	prop.appendChild(xml.createTextNode(main_bundle.manager));
217             	prop_group.appendChild(prop);
218             }
219             if (main_bundle.language != null && main_bundle.language.length() > 0) {
220                 Element prop = xml.createElement("prop");
221             	header.appendChild(prop);
222             	prop.setAttribute("xml:space","preserve");
223             	prop.setAttribute("prop-type","language");
224             	prop.appendChild(xml.createTextNode(main_bundle.language));
225             	prop_group.appendChild(prop);
226             }
227             if (main_bundle.country != null && main_bundle.country.length() > 0) {
228                 Element prop = xml.createElement("prop");
229             	header.appendChild(prop);
230             	prop.setAttribute("xml:space","preserve");
231             	prop.setAttribute("prop-type","country");
232             	prop.appendChild(xml.createTextNode(main_bundle.country));
233             	prop_group.appendChild(prop);
234             }
235             if (main_bundle.variant != null && main_bundle.variant.length() > 0) {
236                 Element prop = xml.createElement("prop");
237             	header.appendChild(prop);
238             	prop.setAttribute("xml:space","preserve");
239             	prop.setAttribute("prop-type","variant");
240             	prop.appendChild(xml.createTextNode(main_bundle.variant));
241             	prop_group.appendChild(prop);
242             }
243         }
244     }
245 
exportFile(RBManager rbm, File directory, String base_name, Bundle main_bundle)246     private void exportFile(RBManager rbm, File directory, String base_name, Bundle main_bundle)
247     	throws IOException
248     {
249         Bundle parent_bundle = null;
250         String parent_bundle_name = null;
251         if (!getLocale(main_bundle).equals("")) {
252         	// If this isn't the root locale, find the parent
253             parent_bundle_name = getParentLocale(getLocale(main_bundle));
254 	        do {
255 	        	parent_bundle = rbm.getBundle(parent_bundle_name);
256 	        	if (parent_bundle != null) {
257 	        		break;
258 	        	}
259 	            parent_bundle_name = getParentLocale(parent_bundle_name);
260 	        } while (!parent_bundle_name.equals(""));
261         }
262 
263 
264         // Find the implementation
265         DocumentBuilder builder;
266         try {
267         	builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
268         }
269         catch (ParserConfigurationException pce) {
270         	throw new IOException(pce.getMessage());
271         }
272 
273         // Create the document
274         Document xml = builder.getDOMImplementation().createDocument(null, "xliff", null);
275 
276         // Fill the document
277         Element root = xml.getDocumentElement();
278         root.setAttribute("version", "1.1");
279         //root.appendChild(root);
280 
281         Element file_elem = xml.createElement("file");
282         String mainLocale = getLocale(main_bundle);
283         Bundle parentBundle = null;
284         if (mainLocale.equals("")) {
285         	file_elem.setAttribute("source-language", getLocale(main_bundle));
286         }
287         else {
288         	file_elem.setAttribute("source-language", parent_bundle_name);
289         	file_elem.setAttribute("target-language", getLocale(main_bundle));
290         }
291         file_elem.setAttribute("datatype", "plaintext");
292         file_elem.setAttribute("date", convertToISO(new Date()));
293         root.appendChild(file_elem);
294 
295         Element header = xml.createElement("header");
296         Element tool = xml.createElement("tool");
297         tool.setAttribute("tool-name", "RBManager");
298         tool.setAttribute("tool-id", "RBManager");
299         tool.setAttribute("tool-version", VERSION);
300         // TODO Add file attribute
301         //header.setAttribute("file", "");
302         header.appendChild(tool);
303         addHeaderProperties(xml, header, main_bundle);
304         file_elem.appendChild(header);
305 
306         Element body = xml.createElement("body");
307         file_elem.appendChild(body);
308 
309         Vector group_v = main_bundle.getGroupsAsVector();
310         Vector parent_group_v = null;
311         if (parent_bundle != null) {
312         	parent_group_v = parent_bundle.getGroupsAsVector();
313         }
314         // Loop through each bundle group in main_bundle
315         for (int i=0; i < group_v.size(); i++) {
316             BundleGroup curr_group = (BundleGroup)group_v.elementAt(i);
317             BundleGroup parent_group = null;
318             if (parent_group_v != null) {
319 	            Enumeration parentGroupIter = parent_group_v.elements();
320 
321 	            while (parentGroupIter.hasMoreElements()) {
322 	            	BundleGroup groupToFind = (BundleGroup)parentGroupIter.nextElement();
323 	            	if (groupToFind.getName().equals(curr_group.getName())) {
324 	            		parent_group = groupToFind;
325 	            		break;
326 	            	}
327 	            }
328             }
329             Element group_elem = xml.createElement("group");
330             group_elem.setAttribute("id", curr_group.getName());
331             if (curr_group.getComment() != null && curr_group.getComment().length() > 1) {
332     	        Element comment_prop = xml.createElement("note");
333     	        comment_prop.setAttribute("xml:space","preserve");
334     	        comment_prop.appendChild(xml.createTextNode(curr_group.getComment()));
335     	        group_elem.appendChild(comment_prop);
336             }
337 
338             Vector group_items = curr_group.getItemsAsVector();
339             for (int j=0; j < group_items.size(); j++) {
340             	BundleItem main_item = (BundleItem)group_items.get(j);
341             	BundleItem parent_item = null;
342             	if (parent_group != null) {
343 	            	Enumeration parentIter = parent_group.getItemsAsVector().elements();
344 	            	BundleItem itemToFind = null;
345 	                while (parentIter.hasMoreElements()) {
346 	                	itemToFind = (BundleItem)parentIter.nextElement();
347 	                	if (itemToFind.getKey().equals(main_item.getKey())) {
348 	                		parent_item = itemToFind;
349 	                		break;
350 	                	}
351 	                }
352             	}
353                 addTransUnit(xml, group_elem, main_item, parent_item);
354                 //group_elem.appendChild(tu);
355             }
356             body.appendChild(group_elem);
357         } // end for - i
358         String suffix = mainLocale;
359         if (!suffix.equals("")) {
360         	suffix = '_' + suffix;
361         }
362         char array[] = suffix.toCharArray();
363         for (int k=0; k < array.length; k++) {
364             if (array[k] == '-')
365                 array[k] = '_';
366         }
367         suffix = String.valueOf(array);
368 
369         // serialize document
370         OutputStreamWriter osw = new OutputStreamWriter(
371         		new FileOutputStream(new File(directory, base_name + suffix + ".xlf")), "UTF-8");
372         try {
373 			Transformer transformer = TransformerFactory.newInstance().newTransformer();
374 			transformer.setOutputProperty(OutputKeys.METHOD, "xml");
375 			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
376 			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
377 			transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, XLIFF_DTD);
378 			transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, XLIFF_PUBLIC_NAME);
379 			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
380 			transformer.transform(new DOMSource(xml), new StreamResult(osw));
381         }
382         catch (TransformerException te) {
383         	throw new IOException(te.getMessage());
384         }
385 
386         osw.close();
387     }
388 }
389