/** * (C) Copyright 2013 Jabylon (http://www.jabylon.org) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.jabylon.properties.types.impl; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Locale; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.jabylon.properties.PropertiesFactory; import org.jabylon.properties.Property; import org.jabylon.properties.PropertyAnnotation; import org.jabylon.properties.PropertyFile; import org.jabylon.properties.types.PropertyAnnotations; import org.jabylon.properties.types.PropertyConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * @author jutzig.dev@googlemail.com * */ public class TMXConverter implements PropertyConverter { private static final Logger LOG = LoggerFactory.getLogger(TMXConverter.class); /* (non-Javadoc) * @see org.jabylon.properties.types.PropertyConverter#load(java.io.InputStream, java.lang.String) */ @Override public PropertyFile load(InputStream in, String encoding) throws IOException { try { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); PropertyFile file = PropertiesFactory.eINSTANCE.createPropertyFile(); TMXHandler handler = new TMXHandler(file); parser.getXMLReader().setEntityResolver(handler); parser.getXMLReader().setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); parser.parse(in, handler); return file; } catch (ParserConfigurationException e) { throw new IOException(e); } catch (SAXException e) { throw new IOException(e); } } /* (non-Javadoc) * @see org.jabylon.properties.types.PropertyConverter#write(java.io.OutputStream, org.jabylon.properties.PropertyFile, java.lang.String) */ @Override public int write(OutputStream out, PropertyFile file, String encoding) throws IOException { throw new UnsupportedOperationException("not yet implemented"); } static class TMXHandler extends DefaultHandler { private PropertyFile file; private String srcLanguage; private Property current; private String currentLanguage; private String targetLanguage; private StringBuilder currentValue; public TMXHandler(PropertyFile file) { this.file = file; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if(is("header",uri,qName,localName)) { srcLanguage = attributes.getValue("", "srclang"); } else if(is("tu",uri,qName,localName)) { current = PropertiesFactory.eINSTANCE.createProperty(); } else if(is("tuv",uri,qName,localName)) { currentLanguage = attributes.getValue("xml:lang"); } else if(is("seg",uri,qName,localName)) { currentValue = new StringBuilder(); } } @Override public void characters(char[] ch, int start, int length) throws SAXException { if(currentValue!=null) currentValue.append(ch, start, length); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if(is("tu",uri,qName,localName)) { if(current!=null) { if(current.getValue()==null || current.getKey()==null) { LOG.error("Invalid property in TMX file: "+current); } else { PropertyAnnotation annotation = PropertiesFactory.eINSTANCE.createPropertyAnnotation(); annotation.setName(PropertyAnnotations.ANNOTATION_LANGUAGE); annotation.getValues().put(PropertyAnnotations.SOURCE_LANGUAGE, normalizeLanguage(srcLanguage)); annotation.getValues().put(PropertyAnnotations.TARGET_LANGUAGE, normalizeLanguage(targetLanguage)); current.getAnnotations().add(annotation); file.getProperties().add(current); } } current = null; } else if(is("seg",uri,qName,localName)) { if(currentValue!=null && current!=null) { if(currentLanguage!=null && currentLanguage.equals(srcLanguage)) { current.setKey(currentValue.toString()); } else { targetLanguage = currentLanguage; current.setValue(currentValue.toString()); } currentValue = null; } } } private String normalizeLanguage(String xmlLang) { if(xmlLang==null || xmlLang.isEmpty()) return "en"; return Locale.forLanguageTag(xmlLang).toString(); } protected boolean is(String expextedElementName, String uri, String qname, String localname) { return expextedElementName.equals(localname) || expextedElementName.equals(qname); } @Override public InputSource resolveEntity(String publicId, String systemId) throws IOException, SAXException { return null; } } }