blob: 87e7b6b6a998fae937e4dbf010ae4ee272ef07ab [file] [log] [blame]
/*
*****************************************************************************
* Copyright (C) 2000-2004, International Business Machines Corporation and *
* others. All Rights Reserved. *
*****************************************************************************
*/
package com.ibm.rbm;
import java.io.*;
import java.util.*;
import java.text.*;
import javax.swing.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.w3c.dom.*;
/**
* This class is a plug-in to RBManager that allows the user to export Resource Bundles
* along with some of the meta-data associated by RBManager to the XLIFF specification.
* For more information on XLIFF visit the web site
* <a href="http://www.lisa.org/xliff/">http://www.lisa.org/xliff/</a>
*
* @author George Rhoten
* @see com.ibm.rbm.RBManager
*/
public class RBxliffExporter extends RBExporter {
private static final String VERSION = "0.7";
private static final String XLIFF_DTD = "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd";
private static final String XLIFF_PUBLIC_NAME = "-//XLIFF//DTD XLIFF//EN";
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
/**
* Default constructor for the XLIFF exporter.
*/
public RBxliffExporter() {
super();
// Initialize the file chooser if necessary
if (chooser == null) {
chooser = new JFileChooser();
chooser.setFileFilter(new javax.swing.filechooser.FileFilter(){
public String getDescription() {
return "XLIFF Files";
}
public boolean accept(File f) {
return (f.isDirectory() || f.getName().endsWith(".xlf"));
}
});
}
}
private String convertToISO(Date d) {
GregorianCalendar gc = new GregorianCalendar();
gc.setTime(d);
return convertToISO(gc);
}
private String convertToISO(GregorianCalendar gc) {
dateFormat.setCalendar(gc);
return dateFormat.format(gc.getTime());
}
private String getLocale(Bundle item) {
String language = item.getLanguageEncoding();
if (language != null && !language.equals("")) {
//language = language.toUpperCase();
String country = item.getCountryEncoding();
if (country != null && !country.equals("")) {
//country = country.toUpperCase();
String variant = item.getVariantEncoding();
if (variant != null && !variant.equals("")) {
//variant = variant.toUpperCase();
return language + "-" + country + "-" + variant;
}
return language + "-" + country;
}
return language;
}
return "";
}
private String getParentLocale(String locale) {
int truncIndex = locale.lastIndexOf('-');
if (truncIndex > 0) {
locale = locale.substring(0, truncIndex);
}
else {
locale = "";
}
return locale;
}
private void addTransUnit(Document xml, Element groupElem, BundleItem item, BundleItem parent_item) {
Element transUnit = xml.createElement("trans-unit");
transUnit.setAttribute("date",convertToISO(item.getModifiedDate()));
transUnit.setAttribute("id",item.getKey());
String sourceOrTarget = "target";
if (parent_item == null) {
sourceOrTarget = "source";
}
else {
Element source = xml.createElement("source");
source.setAttribute("xml:space","preserve");
source.appendChild(xml.createTextNode(parent_item.getTranslation()));
transUnit.appendChild(source);
}
Element target = xml.createElement(sourceOrTarget);
target.setAttribute("xml:space","preserve");
// This is different from the translate attribute
if (item.isTranslated()) {
// TODO Handle the other states in the future.
transUnit.setAttribute("state", "translated");
}
target.appendChild(xml.createTextNode(item.getTranslation()));
transUnit.appendChild(target);
if (item.getComment() != null && item.getComment().length() > 1) {
Element comment_prop = xml.createElement("note");
comment_prop.setAttribute("xml:space","preserve");
comment_prop.appendChild(xml.createTextNode(item.getComment()));
transUnit.appendChild(comment_prop);
}
if ((item.getCreator() != null && item.getCreator().length() > 1)
|| (item.getModifier() != null && item.getModifier().length() > 1))
{
Element transUnit_prop_group_elem = xml.createElement("prop-group");
if (item.getCreator() != null && item.getCreator().length() > 1) {
Element creator_prop = xml.createElement("prop");
creator_prop.setAttribute("prop-type","creator");
creator_prop.appendChild(xml.createTextNode(item.getCreator()));
transUnit_prop_group_elem.appendChild(creator_prop);
}
if (item.getCreator() != null && item.getCreator().length() > 1) {
Element created_prop = xml.createElement("prop");
created_prop.setAttribute("prop-type","created");
created_prop.appendChild(xml.createTextNode(convertToISO(item.getCreatedDate())));
transUnit_prop_group_elem.appendChild(created_prop);
}
if (item.getModifier() != null && item.getModifier().length() > 1) {
Element modifier_prop = xml.createElement("prop");
modifier_prop.setAttribute("prop-type","modifier");
modifier_prop.appendChild(xml.createTextNode(item.getModifier()));
transUnit_prop_group_elem.appendChild(modifier_prop);
}
transUnit.appendChild(transUnit_prop_group_elem);
}
groupElem.appendChild(transUnit);
}
public void export(RBManager rbm) throws IOException {
if (rbm == null)
return;
// Open the Save Dialog
int ret_val = chooser.showSaveDialog(null);
if (ret_val != JFileChooser.APPROVE_OPTION)
return;
// Retrieve basic file information
File file = chooser.getSelectedFile(); // The file(s) we will be working with
File directory = new File(file.getParent()); // The directory we will be writing to
String base_name = file.getName(); // The base name of the files we will write
if (base_name == null || base_name.equals(""))
base_name = rbm.getBaseClass();
if (base_name.endsWith(".xlf"))
base_name = base_name.substring(0,base_name.length()-4);
String file_name = base_name + ".xlf";
Vector bundle_v = rbm.getBundles();
Enumeration bundleIter = bundle_v.elements();
while (bundleIter.hasMoreElements()) {
exportFile(rbm, directory, base_name, (Bundle)bundleIter.nextElement());
}
}
private void addHeaderProperties(Document xml, Element header, Bundle main_bundle) {
if (main_bundle.comment != null && main_bundle.comment.length() > 0) {
Element note = xml.createElement("note");
header.appendChild(note);
note.appendChild(xml.createTextNode(main_bundle.comment));
note.setAttribute("xml:space","preserve");
}
if ((main_bundle.name != null && main_bundle.name.length() > 0)
|| (main_bundle.manager != null && main_bundle.manager.length() > 0)
|| (main_bundle.language != null && main_bundle.language.length() > 0)
|| (main_bundle.country != null && main_bundle.country.length() > 0)
|| (main_bundle.variant != null && main_bundle.variant.length() > 0))
{
Element prop_group = xml.createElement("prop-group");
header.appendChild(prop_group);
if (main_bundle.name != null && main_bundle.name.length() > 0) {
Element prop = xml.createElement("prop");
header.appendChild(prop);
prop.setAttribute("xml:space","preserve");
prop.setAttribute("prop-type","name");
prop.appendChild(xml.createTextNode(main_bundle.name));
prop_group.appendChild(prop);
}
if (main_bundle.manager != null && main_bundle.manager.length() > 0) {
Element prop = xml.createElement("prop");
header.appendChild(prop);
prop.setAttribute("xml:space","preserve");
prop.setAttribute("prop-type","manager");
prop.appendChild(xml.createTextNode(main_bundle.manager));
prop_group.appendChild(prop);
}
if (main_bundle.language != null && main_bundle.language.length() > 0) {
Element prop = xml.createElement("prop");
header.appendChild(prop);
prop.setAttribute("xml:space","preserve");
prop.setAttribute("prop-type","language");
prop.appendChild(xml.createTextNode(main_bundle.language));
prop_group.appendChild(prop);
}
if (main_bundle.country != null && main_bundle.country.length() > 0) {
Element prop = xml.createElement("prop");
header.appendChild(prop);
prop.setAttribute("xml:space","preserve");
prop.setAttribute("prop-type","country");
prop.appendChild(xml.createTextNode(main_bundle.country));
prop_group.appendChild(prop);
}
if (main_bundle.variant != null && main_bundle.variant.length() > 0) {
Element prop = xml.createElement("prop");
header.appendChild(prop);
prop.setAttribute("xml:space","preserve");
prop.setAttribute("prop-type","variant");
prop.appendChild(xml.createTextNode(main_bundle.variant));
prop_group.appendChild(prop);
}
}
}
private void exportFile(RBManager rbm, File directory, String base_name, Bundle main_bundle)
throws IOException
{
Bundle parent_bundle = null;
String parent_bundle_name = null;
if (!getLocale(main_bundle).equals("")) {
// If this isn't the root locale, find the parent
parent_bundle_name = getParentLocale(getLocale(main_bundle));
do {
parent_bundle = rbm.getBundle(parent_bundle_name);
if (parent_bundle != null) {
break;
}
parent_bundle_name = getParentLocale(parent_bundle_name);
} while (!parent_bundle_name.equals(""));
}
// Find the implementation
DocumentBuilder builder;
try {
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
}
catch (ParserConfigurationException pce) {
throw new IOException(pce.getMessage());
}
// Create the document
Document xml = builder.getDOMImplementation().createDocument(null, "xliff", null);
// Fill the document
Element root = xml.getDocumentElement();
root.setAttribute("version", "1.1");
//root.appendChild(root);
Element file_elem = xml.createElement("file");
String mainLocale = getLocale(main_bundle);
Bundle parentBundle = null;
if (mainLocale.equals("")) {
file_elem.setAttribute("source-language", getLocale(main_bundle));
}
else {
file_elem.setAttribute("source-language", parent_bundle_name);
file_elem.setAttribute("target-language", getLocale(main_bundle));
}
file_elem.setAttribute("datatype", "plaintext");
file_elem.setAttribute("date", convertToISO(new Date()));
root.appendChild(file_elem);
Element header = xml.createElement("header");
Element tool = xml.createElement("tool");
tool.setAttribute("tool-name", "RBManager");
tool.setAttribute("tool-id", "RBManager");
tool.setAttribute("tool-version", VERSION);
// TODO Add file attribute
//header.setAttribute("file", "");
header.appendChild(tool);
addHeaderProperties(xml, header, main_bundle);
file_elem.appendChild(header);
Element body = xml.createElement("body");
file_elem.appendChild(body);
Vector group_v = main_bundle.getGroupsAsVector();
Vector parent_group_v = null;
if (parent_bundle != null) {
parent_group_v = parent_bundle.getGroupsAsVector();
}
// Loop through each bundle group in main_bundle
for (int i=0; i < group_v.size(); i++) {
BundleGroup curr_group = (BundleGroup)group_v.elementAt(i);
BundleGroup parent_group = null;
if (parent_group_v != null) {
Enumeration parentGroupIter = parent_group_v.elements();
while (parentGroupIter.hasMoreElements()) {
BundleGroup groupToFind = (BundleGroup)parentGroupIter.nextElement();
if (groupToFind.getName().equals(curr_group.getName())) {
parent_group = groupToFind;
break;
}
}
}
Element group_elem = xml.createElement("group");
group_elem.setAttribute("id", curr_group.getName());
if (curr_group.getComment() != null && curr_group.getComment().length() > 1) {
Element comment_prop = xml.createElement("note");
comment_prop.setAttribute("xml:space","preserve");
comment_prop.appendChild(xml.createTextNode(curr_group.getComment()));
group_elem.appendChild(comment_prop);
}
Vector group_items = curr_group.getItemsAsVector();
for (int j=0; j < group_items.size(); j++) {
BundleItem main_item = (BundleItem)group_items.get(j);
BundleItem parent_item = null;
if (parent_group != null) {
Enumeration parentIter = parent_group.getItemsAsVector().elements();
BundleItem itemToFind = null;
while (parentIter.hasMoreElements()) {
itemToFind = (BundleItem)parentIter.nextElement();
if (itemToFind.getKey().equals(main_item.getKey())) {
parent_item = itemToFind;
break;
}
}
}
addTransUnit(xml, group_elem, main_item, parent_item);
//group_elem.appendChild(tu);
}
body.appendChild(group_elem);
} // end for - i
String suffix = mainLocale;
if (!suffix.equals("")) {
suffix = '_' + suffix;
}
char array[] = suffix.toCharArray();
for (int k=0; k < array.length; k++) {
if (array[k] == '-')
array[k] = '_';
}
suffix = String.valueOf(array);
// serialize document
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream(new File(directory, base_name + suffix + ".xlf")), "UTF-8");
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, XLIFF_DTD);
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, XLIFF_PUBLIC_NAME);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.transform(new DOMSource(xml), new StreamResult(osw));
}
catch (TransformerException te) {
throw new IOException(te.getMessage());
}
osw.close();
}
}