| /******************************************************************************* |
| * Crown Copyright (c) 2006, 2012, Copyright (c) 2006, 2008 Kestral Computing P/L. |
| * 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 |
| * |
| * Contributors: |
| * Kestral Computing P/L - initial implementation |
| * Werner Keil - added static imports |
| *******************************************************************************/ |
| |
| package org.eclipse.uomo.ucum.parsers; |
| |
| import static org.eclipse.uomo.ucum.model.ConceptKind.*; |
| import static org.xmlpull.v1.XmlPullParser.*; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.math.BigDecimal; |
| import java.text.ParseException; |
| import java.util.Date; |
| |
| import org.apache.commons.lang.StringUtils; |
| import org.eclipse.uomo.core.UOMoException; |
| import org.eclipse.uomo.ucum.internal.Messages; |
| import org.eclipse.uomo.ucum.model.BaseUnit; |
| import org.eclipse.uomo.ucum.model.DefinedUnit; |
| import org.eclipse.uomo.ucum.model.Prefix; |
| import org.eclipse.uomo.ucum.model.UcumModel; |
| import org.eclipse.uomo.ucum.model.Value; |
| import org.eclipse.uomo.util.Parser; |
| import org.xmlpull.v1.XmlPullParser; |
| import org.xmlpull.v1.XmlPullParserException; |
| import org.xmlpull.v1.XmlPullParserFactory; |
| |
| import com.ibm.icu.text.DateFormat; |
| import com.ibm.icu.text.SimpleDateFormat; |
| |
| |
| /** |
| * Parses the file ucum-essense.xml |
| * |
| * @author Grahame Grieve |
| * @author Werner Keil |
| */ |
| |
| public class DefinitionParser implements Parser<String, UcumModel> { |
| |
| public UcumModel parse(String filename) throws UOMoException { |
| try { |
| return parse(new FileInputStream(new File(filename))); |
| } catch (XmlPullParserException x) { |
| throw new UOMoException(x); |
| } catch (ParseException p) { |
| throw new UOMoException(p); |
| } catch (IOException i) { |
| throw new UOMoException(i); |
| } |
| } |
| |
| public UcumModel parse(InputStream stream) throws XmlPullParserException, IOException, ParseException { |
| XmlPullParserFactory factory = XmlPullParserFactory.newInstance( |
| System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null); |
| factory.setNamespaceAware(true); |
| XmlPullParser xpp = factory.newPullParser(); |
| |
| xpp.setInput(stream, null); |
| |
| int eventType = xpp.next(); |
| if (eventType != START_TAG) |
| throw new XmlPullParserException(Messages.DefinitionParser_0); |
| if (!xpp.getName().equals("root")) //$NON-NLS-1$ |
| throw new XmlPullParserException(Messages.DefinitionParser_2+xpp.getName()+Messages.DefinitionParser_3); |
| final DateFormat fmt = new SimpleDateFormat(Messages.DefinitionParser_DateFormat); |
| Date date = fmt.parse(xpp.getAttributeValue(null, "revision-date").substring(7, 32)); //$NON-NLS-1$ |
| UcumModel root = new UcumModel(xpp.getAttributeValue(null, "version"), xpp.getAttributeValue(null, "revision"), date); //$NON-NLS-1$ //$NON-NLS-2$ |
| xpp.next(); |
| while (xpp.getEventType() != END_TAG) { |
| if (xpp.getEventType() == TEXT) { |
| if (StringUtils.isWhitespace(xpp.getText())) |
| xpp.next(); |
| else |
| throw new XmlPullParserException(Messages.DefinitionParser_8+xpp.getText()); |
| } else if (xpp.getName().equals(PREFIX.visibleName())) |
| root.getPrefixes().add(parsePrefix(xpp)); |
| else if (xpp.getName().equals(BASEUNIT.visibleName())) |
| root.getBaseUnits().add(parseBaseUnit(xpp)); |
| else if (xpp.getName().equals(UNIT.visibleName())) |
| root.getDefinedUnits().add(parseUnit(xpp)); |
| else |
| throw new XmlPullParserException(Messages.DefinitionParser_9+xpp.getName()); |
| } |
| return root; |
| } |
| |
| private DefinedUnit parseUnit(XmlPullParser xpp) throws XmlPullParserException, IOException { |
| DefinedUnit unit = new DefinedUnit(xpp.getAttributeValue(null, "Code"), xpp.getAttributeValue(null, "CODE")); //$NON-NLS-1$ //$NON-NLS-2$ |
| unit.setMetric("yes".equals(xpp.getAttributeValue(null, "isMetric"))); //$NON-NLS-1$ //$NON-NLS-2$ |
| unit.setSpecial("yes".equals(xpp.getAttributeValue(null, "isSpecial"))); //$NON-NLS-1$ //$NON-NLS-2$ |
| unit.setClass_(xpp.getAttributeValue(null, "class")); //$NON-NLS-1$ |
| xpp.next(); |
| skipWhitespace(xpp); |
| while (xpp.getEventType() == START_TAG && "name".equals(xpp.getName())) //$NON-NLS-1$ |
| unit.getNames().add(readElement(xpp, "name", UNIT.visibleName()+" "+unit.getCode(), false)); //$NON-NLS-1$ //$NON-NLS-2$ |
| if (xpp.getEventType() == START_TAG && "printSymbol".equals(xpp.getName())) //$NON-NLS-1$ |
| unit.setPrintSymbol(readElement(xpp, "printSymbol", UNIT.visibleName()+" "+unit.getCode(), true)); //$NON-NLS-1$ //$NON-NLS-2$ |
| unit.setProperty(readElement(xpp, "property", UNIT.visibleName()+" "+unit.getCode(), false)); //$NON-NLS-1$ //$NON-NLS-2$ |
| unit.setValue(parseValue(xpp, "unit "+unit.getCode())); //$NON-NLS-1$ |
| xpp.next(); |
| skipWhitespace(xpp); |
| return unit; |
| } |
| |
| private Value<?> parseValue(XmlPullParser xpp, String context) throws XmlPullParserException, IOException { |
| checkAtElement(xpp, "value", context); //$NON-NLS-1$ |
| BigDecimal val = null; |
| if (xpp.getAttributeValue(null, "value") != null) //$NON-NLS-1$ |
| try { |
| val = new BigDecimal(xpp.getAttributeValue(null, "value")); //$NON-NLS-1$ |
| } catch (NumberFormatException e) { |
| throw new XmlPullParserException(Messages.DefinitionParser_29+context+Messages.DefinitionParser_30+e.getMessage()); |
| } |
| @SuppressWarnings("rawtypes") |
| Value<?> value = new Value(xpp.getAttributeValue(null, "Unit"), xpp.getAttributeValue(null, "UNIT"), val); //$NON-NLS-1$ //$NON-NLS-2$ |
| value.setText(readElement(xpp, "value", context, true)); //$NON-NLS-1$ |
| return value; |
| } |
| |
| private BaseUnit parseBaseUnit(XmlPullParser xpp) throws XmlPullParserException, IOException { |
| BaseUnit base = new BaseUnit(xpp.getAttributeValue(null, "Code"), xpp.getAttributeValue(null, "CODE")); //$NON-NLS-1$ //$NON-NLS-2$ |
| base.setDim(xpp.getAttributeValue(null, "dim").charAt(0)); //$NON-NLS-1$ |
| xpp.next(); |
| skipWhitespace(xpp); |
| base.getNames().add(readElement(xpp, "name", BASEUNIT.visibleName()+" "+base.getCode(), false)); //$NON-NLS-1$ //$NON-NLS-2$ |
| base.setPrintSymbol(readElement(xpp, "printSymbol", BASEUNIT.visibleName()+" "+base.getCode(), false)); //$NON-NLS-1$ //$NON-NLS-2$ |
| base.setProperty(readElement(xpp, "property", BASEUNIT.visibleName()+" "+base.getCode(), false)); //$NON-NLS-1$ //$NON-NLS-2$ |
| xpp.next(); |
| skipWhitespace(xpp); |
| return base; |
| } |
| |
| private Prefix parsePrefix(XmlPullParser xpp) throws XmlPullParserException, IOException { |
| Prefix prefix = new Prefix(xpp.getAttributeValue(null, "Code"), xpp.getAttributeValue(null, "CODE")); //$NON-NLS-1$ //$NON-NLS-2$ |
| xpp.next(); |
| skipWhitespace(xpp); |
| prefix.getNames().add(readElement(xpp, "name", PREFIX.visibleName()+" "+prefix.getCode(), false)); //$NON-NLS-1$ //$NON-NLS-2$ |
| prefix.setPrintSymbol(readElement(xpp, "printSymbol", PREFIX.visibleName()+" "+prefix.getCode(), false)); //$NON-NLS-1$ //$NON-NLS-2$ |
| checkAtElement(xpp, "value", PREFIX.visibleName()+" "+prefix.getCode()); //$NON-NLS-1$ //$NON-NLS-2$ |
| prefix.setValue(new BigDecimal(xpp.getAttributeValue(null, "value"))); //$NON-NLS-1$ |
| readElement(xpp, "value", PREFIX.visibleName()+" "+prefix.getCode(), true); //$NON-NLS-1$ //$NON-NLS-2$ |
| xpp.next(); |
| skipWhitespace(xpp); |
| return prefix; |
| } |
| |
| private String readElement(XmlPullParser xpp, String name, String context, boolean complex) throws XmlPullParserException, IOException { |
| checkAtElement(xpp, name, context); |
| xpp.next(); |
| skipWhitespace(xpp); |
| String val = null; |
| if (complex) { |
| val = readText(xpp); |
| } else if (xpp.getEventType() == TEXT) { |
| val = xpp.getText(); |
| xpp.next(); |
| skipWhitespace(xpp); |
| } |
| if (xpp.getEventType() != END_TAG) { |
| throw new XmlPullParserException(Messages.DefinitionParser_54+context); |
| } |
| xpp.next(); |
| skipWhitespace(xpp); |
| return val; |
| } |
| |
| private String readText(XmlPullParser xpp) throws XmlPullParserException, IOException { |
| StringBuilder bldr = new StringBuilder(); |
| while (xpp.getEventType() != END_TAG) { |
| if (xpp.getEventType() == TEXT) { |
| bldr.append(xpp.getText()); |
| xpp.next(); |
| } else { |
| xpp.next(); |
| bldr.append(readText(xpp)); |
| xpp.next(); |
| skipWhitespace(xpp); |
| } |
| } |
| return bldr.toString(); |
| } |
| |
| private void skipWhitespace(XmlPullParser xpp) throws XmlPullParserException, IOException { |
| while (xpp.getEventType() == TEXT && StringUtils.isWhitespace(xpp.getText())) |
| xpp.next(); |
| } |
| |
| private void checkAtElement(XmlPullParser xpp, String name, String context) throws XmlPullParserException { |
| if (xpp.getEventType() != START_TAG) |
| throw new XmlPullParserException(Messages.DefinitionParser_55+name+Messages.DefinitionParser_56+Integer.toString(xpp.getEventType())+Messages.DefinitionParser_57+context); |
| if (!xpp.getName().equals(name)) |
| throw new XmlPullParserException(Messages.DefinitionParser_58+name+Messages.DefinitionParser_59+xpp.getName()+Messages.DefinitionParser_60+context); |
| } |
| } |