X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.databoard%2Fsrc%2Forg%2Fsimantics%2Fdataboard%2Fparser%2Frepository%2FDataValueRepository.java;h=9912e9ac6529fb5f8eb33913420f2a27207d4262;hb=refs%2Fchanges%2F38%2F238%2F2;hp=0bba95ada2cfde5f657933b07d6e6532fbb9c9cf;hpb=24e2b34260f219f0d1644ca7a138894980e25b14;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/parser/repository/DataValueRepository.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/parser/repository/DataValueRepository.java
index 0bba95ada..9912e9ac6 100644
--- a/bundles/org.simantics.databoard/src/org/simantics/databoard/parser/repository/DataValueRepository.java
+++ b/bundles/org.simantics.databoard/src/org/simantics/databoard/parser/repository/DataValueRepository.java
@@ -1,644 +1,644 @@
-/*******************************************************************************
- * Copyright (c) 2010 Association for Decentralized Information Management in
- * Industry THTH ry.
- * 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:
- * VTT Technical Research Centre of Finland - initial API and implementation
- *******************************************************************************/
-package org.simantics.databoard.parser.repository;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.IdentityHashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import org.simantics.databoard.Bindings;
-import org.simantics.databoard.Datatypes;
-import org.simantics.databoard.binding.ArrayBinding;
-import org.simantics.databoard.binding.Binding;
-import org.simantics.databoard.binding.BooleanBinding;
-import org.simantics.databoard.binding.ByteBinding;
-import org.simantics.databoard.binding.DoubleBinding;
-import org.simantics.databoard.binding.FloatBinding;
-import org.simantics.databoard.binding.IntegerBinding;
-import org.simantics.databoard.binding.LongBinding;
-import org.simantics.databoard.binding.MapBinding;
-import org.simantics.databoard.binding.OptionalBinding;
-import org.simantics.databoard.binding.RecordBinding;
-import org.simantics.databoard.binding.StringBinding;
-import org.simantics.databoard.binding.UnionBinding;
-import org.simantics.databoard.binding.VariantBinding;
-import org.simantics.databoard.binding.error.BindingConstructionException;
-import org.simantics.databoard.binding.error.BindingException;
-import org.simantics.databoard.binding.error.RuntimeBindingException;
-import org.simantics.databoard.binding.factory.BindingScheme;
-import org.simantics.databoard.binding.mutable.MutableVariant;
-import org.simantics.databoard.file.RuntimeIOException;
-import org.simantics.databoard.parser.DataParser;
-import org.simantics.databoard.parser.DataValuePrinter;
-import org.simantics.databoard.parser.ParseException;
-import org.simantics.databoard.parser.PrintFormat;
-import org.simantics.databoard.parser.TokenMgrError;
-import org.simantics.databoard.parser.ast.value.AstArray;
-import org.simantics.databoard.parser.ast.value.AstBoolean;
-import org.simantics.databoard.parser.ast.value.AstComponentAssignment;
-import org.simantics.databoard.parser.ast.value.AstFloat;
-import org.simantics.databoard.parser.ast.value.AstInteger;
-import org.simantics.databoard.parser.ast.value.AstMap;
-import org.simantics.databoard.parser.ast.value.AstMapAssignment;
-import org.simantics.databoard.parser.ast.value.AstNull;
-import org.simantics.databoard.parser.ast.value.AstRecord;
-import org.simantics.databoard.parser.ast.value.AstReference;
-import org.simantics.databoard.parser.ast.value.AstString;
-import org.simantics.databoard.parser.ast.value.AstTaggedValue;
-import org.simantics.databoard.parser.ast.value.AstTuple;
-import org.simantics.databoard.parser.ast.value.AstValue;
-import org.simantics.databoard.parser.ast.value.AstValueDefinition;
-import org.simantics.databoard.parser.ast.value.AstVariant;
-import org.simantics.databoard.parser.ast.value.visitor.AstValueVisitor;
-import org.simantics.databoard.parser.unparsing.DataTypePrinter;
-import org.simantics.databoard.type.Component;
-import org.simantics.databoard.type.Datatype;
-import org.simantics.databoard.type.MapType;
-import org.simantics.databoard.type.RecordType;
-import org.simantics.databoard.type.UnionType;
-
-/**
- * Data value repository is a collection of name data values.
- * Each value is associated with type.
- *
- *
- * It can also translate data lines and value texts to objects and
- * print values as
- *
- *
- *
- * @author Hannu Niemistö
- */
-public class DataValueRepository {
-
- // Type respository to convert
- DataTypeRepository typeRepository = Datatypes.datatypeRepository;
-
- // Scheme to convert values
- BindingScheme bindingScheme = Bindings.mutableBindingFactory;
-
- /** Stored values */
- Map values = new HashMap();
- Map nameMap = new IdentityHashMap();
-
- public MutableVariant get(String name) {
- return values.get(name);
- }
-
- public String getName(Object value) {
- return nameMap.get(value);
- }
-
- public void put(String name, Binding binding, Object value) {
- put(name, new MutableVariant(binding, value));
- }
-
- public void put(String name, MutableVariant value) {
- values.put(name, value);
- nameMap.put(value.getValue(), name);
- }
-
- public MutableVariant remove(String name) {
- MutableVariant value = values.remove(name);
- if (value==null) return null;
- nameMap.remove(value.getValue());
- return value;
- }
-
- public void clear() {
- values.clear();
- nameMap.clear();
- }
-
- /**
- * Get a view of the value names in this repository
- *
- * @return names
- */
- public Set getValueNames() {
- return values.keySet();
- }
-
- /**
- * Translates a data value from an abstract syntax tree to an object by the binding.
- *
- * @param value
- * @param binding
- * @return value
- * @throws DataTypeSyntaxError
- */
- public Object translate(AstValue value, Binding binding) throws DataTypeSyntaxError {
- try {
- if(value instanceof AstReference) {
- String name = ((AstReference)value).name;
- MutableVariant v = get(name);
- if(v == null) {
- if(binding instanceof UnionBinding) {
- UnionBinding b = (UnionBinding)binding;
- UnionType type = b.type();
- Integer index = type.getComponentIndex(name);
- if(index != null)
- try {
- return b.create(index,
- b.getComponentBinding(index).createDefault());
- } catch(BindingException e) {
- throw new DataTypeSyntaxError(e);
- }
- }
- throw new DataTypeSyntaxError("Undefined reference to " + name + ".");
- }
- return Bindings.adaptUnchecked(v.getValue(), v.getBinding(), binding);
- }
- return binding.accept(new ValueTranslator(value));
- } catch(ValueTranslationRuntimeException e) {
- throw new DataTypeSyntaxError(e);
- }
- }
-
- /**
- * Translates a data value from a string to an object by the binding.
- * @param value
- * @param binding
- * @return value
- * @throws DataTypeSyntaxError
- */
- public Object translate(String value, Binding binding) throws DataTypeSyntaxError {
- try {
- return translate(new DataParser(new StringReader(value)).value(), binding);
- } catch (TokenMgrError e) {
- throw new DataTypeSyntaxError(e);
- } catch (ParseException e) {
- throw new DataTypeSyntaxError(e);
- }
- }
-
- /**
- * Adds a value definition to the repository
- * @param def
- * @throws DataTypeSyntaxError
- */
- public void addValueDefinition(AstValueDefinition def) throws DataTypeSyntaxError {
- Datatype type = typeRepository.translate(def.type);
- Binding binding = Bindings.getMutableBinding(type);
- MutableVariant variant = new MutableVariant(binding, translate(def.value, binding));
- values.put(def.name, variant);
- nameMap.put(variant.getValue(), def.name);
- }
-
- /**
- * Adds a value definition to the repository
- * @param def
- * @return name
- * @throws DataTypeSyntaxError
- */
- public String addValueDefinition(String def) throws DataTypeSyntaxError {
- try {
- StringReader reader = new StringReader(def);
- DataParser parser = new DataParser( reader );
- AstValueDefinition valueAstDef = parser.valueDefinition();
- addValueDefinition( valueAstDef );
- return valueAstDef.name;
- } catch (TokenMgrError e) {
- throw new DataTypeSyntaxError(e);
- } catch (ParseException e) {
- throw new DataTypeSyntaxError(e);
- }
- }
-
- /**
- * Adds multiple value definitions to the repository
- *
- * @param defs
- * @throws DataTypeSyntaxError
- */
- public void addValueDefinitions(Collection defs) throws DataTypeSyntaxError {
- // TODO recursive definitions
- for(AstValueDefinition def : defs)
- addValueDefinition(def);
- }
-
- /**
- * Adds multiple value definitions to the repository
- * @param def
- * @throws DataTypeSyntaxError
- */
- public void addValueDefinitions(String def) throws DataTypeSyntaxError {
- try {
- addValueDefinitions(new DataParser(new StringReader(def)).valueDefinitions());
- } catch (TokenMgrError e) {
- throw new DataTypeSyntaxError(e);
- } catch (ParseException e) {
- throw new DataTypeSyntaxError(e);
- }
- }
-
- public DataTypeRepository getTypeRepository() {
- return typeRepository;
- }
-
- public void setTypeRepository(DataTypeRepository typeRepository) {
- this.typeRepository = typeRepository;
- }
-
- public BindingScheme getBindingScheme() {
- return bindingScheme;
- }
-
- public void setBindingScheme(BindingScheme bindingScheme) {
- this.bindingScheme = bindingScheme;
- }
-
- /**
- * Print the content part of a data value. This excludes the name and type of the value.
- *
- * @param valueName
- * @return value or null
if value doesn't exist
- * @throws BindingException
- * @throws IOException
- */
- public String printValue(String valueName) throws IOException, BindingException {
- MutableVariant value = get(valueName);
- if (value==null) return null;
- StringBuilder sb = new StringBuilder();
- DataValuePrinter vp = new DataValuePrinter(sb, this);
- vp.print(value);
- return sb.toString();
- }
-
- /**
- * Print the whole value repository
- *
- * @param sb
- * @throws IOException
- * @throws BindingException
- */
- public void print(StringBuilder sb)
- throws IOException, BindingException
- {
- DataValuePrinter vp = new DataValuePrinter(sb, this);
- vp.setFormat( PrintFormat.SINGLE_LINE );
- DataTypePrinter tp = new DataTypePrinter( sb );
- tp.setLinefeed( false );
-
- for (Entry e : values.entrySet()) {
- String name = e.getKey();
- MutableVariant value = e.getValue();
- Datatype type = value.type();
- sb.append( name+" : " );
- tp.print(type);
- sb.append( " = " );
- vp.print(value);
- sb.append("\n");
- }
- }
-
- /**
- * Print the whole data value repository as a single multiline string
- *
- * @throws RuntimeBindingException
- * @throws {@link RuntimeIOException}
- */
- @Override
- public String toString() {
- try {
- StringBuilder sb = new StringBuilder();
- print(sb);
- return sb.toString();
- } catch (BindingException e) {
- throw new RuntimeBindingException(e);
- } catch (IOException e) {
- throw new RuntimeIOException(e);
- }
- }
-
- /**
- * Gives a data type to a value heuristically.
- */
- public Datatype guessDataType(AstValue value) throws DataTypeSyntaxError {
- return value.accept(guessDataType);
- }
-
- /**
- * Gives a data type to a value heuristically.
- */
- public Datatype guessDataType(String value) throws DataTypeSyntaxError {
- try {
- return guessDataType(new DataParser(new StringReader(value)).value());
- } catch (TokenMgrError e) {
- throw new DataTypeSyntaxError(e);
- } catch (ParseException e) {
- throw new DataTypeSyntaxError(e);
- }
- }
-
- class ValueTranslator implements Binding.Visitor {
-
- AstValue value;
-
- public ValueTranslator(AstValue value) {
- this.value = value;
- }
-
- private ValueTranslationRuntimeException typeError(Binding expectedType, AstValue actualValue) {
- throw new ValueTranslationRuntimeException("Expected " + expectedType.type().toSingleLineString() +
- " but got " + actualValue.getClass().getSimpleName() + ".");
- }
-
- @Override
- public Object visit(ArrayBinding b) {
- if(value instanceof AstArray) {
- AstArray array = (AstArray)value;
- Object[] components = new Object[array.elements.size()];
- Binding componentBinding = b.getComponentBinding();
- int i=0;
- for(AstValue component : array.elements) {
- value = component;
- components[i++] = componentBinding.accept(this);
- }
- return b.createUnchecked(components);
- }
- throw typeError(b, value);
- }
-
- @Override
- public Object visit(BooleanBinding b) {
- if(value instanceof AstBoolean) {
- return b.createUnchecked(((AstBoolean)value).value);
- }
- throw typeError(b, value);
- }
-
- @Override
- public Object visit(DoubleBinding b) {
- if(value instanceof AstFloat) {
- return b.createUnchecked(((AstFloat)value).value);
- }
- if(value instanceof AstInteger) {
- return b.createUnchecked(((AstInteger)value).value);
- }
- throw typeError(b, value);
- }
-
- @Override
- public Object visit(FloatBinding b) {
- if(value instanceof AstFloat) {
- return b.createUnchecked(((AstFloat)value).value);
- }
- if(value instanceof AstInteger) {
- return b.createUnchecked(((AstInteger)value).value);
- }
- throw typeError(b, value);
- }
-
- @Override
- public Object visit(IntegerBinding b) {
- if(value instanceof AstInteger) {
- return b.createUnchecked(((AstInteger)value).value);
- }
- throw typeError(b, value);
- }
-
- @Override
- public Object visit(ByteBinding b) {
- if(value instanceof AstInteger) {
- return b.createUnchecked(((AstInteger)value).value);
- }
- throw typeError(b, value);
- }
-
- @Override
- public Object visit(LongBinding b) {
- if(value instanceof AstInteger) {
- return b.createUnchecked(((AstInteger)value).value);
- }
- throw typeError(b, value);
- }
-
- @Override
- public Object visit(OptionalBinding b) {
- if(value == AstNull.NULL)
- return b.createNoValueUnchecked();
- else
- return b.createValueUnchecked(b.getComponentBinding().accept(this));
- }
-
- @Override
- public Object visit(RecordBinding b) {
- if(value instanceof AstRecord) {
- AstRecord record = (AstRecord)value;
- Object[] components = new Object[b.getComponentCount()];
- boolean[] assigned = new boolean[b.getComponentCount()];
- for(AstComponentAssignment assignment : record.components) {
- value = assignment.value;
- Integer index = b.type().getComponentIndex(assignment.component);
- if(index == null)
- throw new ValueTranslationRuntimeException("Invalid record component " + assignment.component + ".");
- components[index] = b.getComponentBinding(index).accept(this);
- assigned[index] = true;
- }
- for(int i=0;i guessDataType = new AstValueVisitor() {
-
- @Override
- public Datatype visit(AstArray astArray) {
- if(astArray.elements.isEmpty())
- throw new ValueTranslationRuntimeException("Cannot guess the data type of empty array.");
- return astArray.elements.get(0).accept(this);
- }
-
- @Override
- public Datatype visit(AstBoolean astBoolean) {
- return Datatypes.BOOLEAN;
- }
-
- @Override
- public Datatype visit(AstFloat astFloat) {
- return Datatypes.DOUBLE;
- }
-
- @Override
- public Datatype visit(AstInteger astInteger) {
- return Datatypes.INTEGER;
- }
-
- @Override
- public Datatype visit(AstMap astMap) {
- if(astMap.components.isEmpty())
- throw new ValueTranslationRuntimeException("Cannot guess the data type of empty map.");
- AstMapAssignment assignment = astMap.components.get(0);
- return new MapType(assignment.key.accept(this), assignment.value.accept(this));
- }
-
- @Override
- public Datatype visit(AstNull astNull) {
- throw new ValueTranslationRuntimeException("Cannot guess the data type");
- }
-
- @Override
- public Datatype visit(AstRecord astRecord) {
- Component[] components = new Component[astRecord.components.size()];
- int i = 0;
- for(AstComponentAssignment assignment : astRecord.components) {
- components[i++] = new Component(
- assignment.component,
- assignment.value.accept(this)
- );
- }
- return new RecordType(false, components);
- }
-
- @Override
- public Datatype visit(AstReference astReference) {
- MutableVariant v = get(astReference.name);
- if(v == null)
- throw new ValueTranslationRuntimeException("Undefined reference to " + astReference.name + ".");
- return v.type();
- }
-
- @Override
- public Datatype visit(AstString astString) {
- return Datatypes.STRING;
- }
-
- @Override
- public Datatype visit(AstTaggedValue astTaggedValue) {
- // Guessed datatype would be a union with just one component. Not very useful.
- throw new ValueTranslationRuntimeException("Cannot guess the data type of tagged value");
- }
-
- @Override
- public Datatype visit(AstTuple astTuple) {
- Component[] components = new Component[astTuple.elements.size()];
- int i = 0;
- for(AstValue value : astTuple.elements) {
- components[i] = new Component(
- Integer.toString(i),
- value.accept(this)
- );
- ++i;
- }
- return new RecordType(false, components);
- }
-
- @Override
- public Datatype visit(AstVariant astVariant) {
- return Datatypes.VARIANT;
- }
- };
-
-
-}
+/*******************************************************************************
+ * Copyright (c) 2010 Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * 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:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.databoard.parser.repository;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.Datatypes;
+import org.simantics.databoard.binding.ArrayBinding;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.BooleanBinding;
+import org.simantics.databoard.binding.ByteBinding;
+import org.simantics.databoard.binding.DoubleBinding;
+import org.simantics.databoard.binding.FloatBinding;
+import org.simantics.databoard.binding.IntegerBinding;
+import org.simantics.databoard.binding.LongBinding;
+import org.simantics.databoard.binding.MapBinding;
+import org.simantics.databoard.binding.OptionalBinding;
+import org.simantics.databoard.binding.RecordBinding;
+import org.simantics.databoard.binding.StringBinding;
+import org.simantics.databoard.binding.UnionBinding;
+import org.simantics.databoard.binding.VariantBinding;
+import org.simantics.databoard.binding.error.BindingConstructionException;
+import org.simantics.databoard.binding.error.BindingException;
+import org.simantics.databoard.binding.error.RuntimeBindingException;
+import org.simantics.databoard.binding.factory.BindingScheme;
+import org.simantics.databoard.binding.mutable.MutableVariant;
+import org.simantics.databoard.file.RuntimeIOException;
+import org.simantics.databoard.parser.DataParser;
+import org.simantics.databoard.parser.DataValuePrinter;
+import org.simantics.databoard.parser.ParseException;
+import org.simantics.databoard.parser.PrintFormat;
+import org.simantics.databoard.parser.TokenMgrError;
+import org.simantics.databoard.parser.ast.value.AstArray;
+import org.simantics.databoard.parser.ast.value.AstBoolean;
+import org.simantics.databoard.parser.ast.value.AstComponentAssignment;
+import org.simantics.databoard.parser.ast.value.AstFloat;
+import org.simantics.databoard.parser.ast.value.AstInteger;
+import org.simantics.databoard.parser.ast.value.AstMap;
+import org.simantics.databoard.parser.ast.value.AstMapAssignment;
+import org.simantics.databoard.parser.ast.value.AstNull;
+import org.simantics.databoard.parser.ast.value.AstRecord;
+import org.simantics.databoard.parser.ast.value.AstReference;
+import org.simantics.databoard.parser.ast.value.AstString;
+import org.simantics.databoard.parser.ast.value.AstTaggedValue;
+import org.simantics.databoard.parser.ast.value.AstTuple;
+import org.simantics.databoard.parser.ast.value.AstValue;
+import org.simantics.databoard.parser.ast.value.AstValueDefinition;
+import org.simantics.databoard.parser.ast.value.AstVariant;
+import org.simantics.databoard.parser.ast.value.visitor.AstValueVisitor;
+import org.simantics.databoard.parser.unparsing.DataTypePrinter;
+import org.simantics.databoard.type.Component;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.databoard.type.MapType;
+import org.simantics.databoard.type.RecordType;
+import org.simantics.databoard.type.UnionType;
+
+/**
+ * Data value repository is a collection of name data values.
+ * Each value is associated with type.
+ *
+ *
+ * It can also translate data lines and value texts to objects and
+ * print values as
+ *
+ *
+ *
+ * @author Hannu Niemistö
+ */
+public class DataValueRepository {
+
+ // Type respository to convert
+ DataTypeRepository typeRepository = Datatypes.datatypeRepository;
+
+ // Scheme to convert values
+ BindingScheme bindingScheme = Bindings.mutableBindingFactory;
+
+ /** Stored values */
+ Map values = new HashMap();
+ Map nameMap = new IdentityHashMap();
+
+ public MutableVariant get(String name) {
+ return values.get(name);
+ }
+
+ public String getName(Object value) {
+ return nameMap.get(value);
+ }
+
+ public void put(String name, Binding binding, Object value) {
+ put(name, new MutableVariant(binding, value));
+ }
+
+ public void put(String name, MutableVariant value) {
+ values.put(name, value);
+ nameMap.put(value.getValue(), name);
+ }
+
+ public MutableVariant remove(String name) {
+ MutableVariant value = values.remove(name);
+ if (value==null) return null;
+ nameMap.remove(value.getValue());
+ return value;
+ }
+
+ public void clear() {
+ values.clear();
+ nameMap.clear();
+ }
+
+ /**
+ * Get a view of the value names in this repository
+ *
+ * @return names
+ */
+ public Set getValueNames() {
+ return values.keySet();
+ }
+
+ /**
+ * Translates a data value from an abstract syntax tree to an object by the binding.
+ *
+ * @param value
+ * @param binding
+ * @return value
+ * @throws DataTypeSyntaxError
+ */
+ public Object translate(AstValue value, Binding binding) throws DataTypeSyntaxError {
+ try {
+ if(value instanceof AstReference) {
+ String name = ((AstReference)value).name;
+ MutableVariant v = get(name);
+ if(v == null) {
+ if(binding instanceof UnionBinding) {
+ UnionBinding b = (UnionBinding)binding;
+ UnionType type = b.type();
+ Integer index = type.getComponentIndex(name);
+ if(index != null)
+ try {
+ return b.create(index,
+ b.getComponentBinding(index).createDefault());
+ } catch(BindingException e) {
+ throw new DataTypeSyntaxError(e);
+ }
+ }
+ throw new DataTypeSyntaxError("Undefined reference to " + name + ".");
+ }
+ return Bindings.adaptUnchecked(v.getValue(), v.getBinding(), binding);
+ }
+ return binding.accept(new ValueTranslator(value));
+ } catch(ValueTranslationRuntimeException e) {
+ throw new DataTypeSyntaxError(e);
+ }
+ }
+
+ /**
+ * Translates a data value from a string to an object by the binding.
+ * @param value
+ * @param binding
+ * @return value
+ * @throws DataTypeSyntaxError
+ */
+ public Object translate(String value, Binding binding) throws DataTypeSyntaxError {
+ try {
+ return translate(new DataParser(new StringReader(value)).value(), binding);
+ } catch (TokenMgrError e) {
+ throw new DataTypeSyntaxError(e);
+ } catch (ParseException e) {
+ throw new DataTypeSyntaxError(e);
+ }
+ }
+
+ /**
+ * Adds a value definition to the repository
+ * @param def
+ * @throws DataTypeSyntaxError
+ */
+ public void addValueDefinition(AstValueDefinition def) throws DataTypeSyntaxError {
+ Datatype type = typeRepository.translate(def.type);
+ Binding binding = Bindings.getMutableBinding(type);
+ MutableVariant variant = new MutableVariant(binding, translate(def.value, binding));
+ values.put(def.name, variant);
+ nameMap.put(variant.getValue(), def.name);
+ }
+
+ /**
+ * Adds a value definition to the repository
+ * @param def
+ * @return name
+ * @throws DataTypeSyntaxError
+ */
+ public String addValueDefinition(String def) throws DataTypeSyntaxError {
+ try {
+ StringReader reader = new StringReader(def);
+ DataParser parser = new DataParser( reader );
+ AstValueDefinition valueAstDef = parser.valueDefinition();
+ addValueDefinition( valueAstDef );
+ return valueAstDef.name;
+ } catch (TokenMgrError e) {
+ throw new DataTypeSyntaxError(e);
+ } catch (ParseException e) {
+ throw new DataTypeSyntaxError(e);
+ }
+ }
+
+ /**
+ * Adds multiple value definitions to the repository
+ *
+ * @param defs
+ * @throws DataTypeSyntaxError
+ */
+ public void addValueDefinitions(Collection defs) throws DataTypeSyntaxError {
+ // TODO recursive definitions
+ for(AstValueDefinition def : defs)
+ addValueDefinition(def);
+ }
+
+ /**
+ * Adds multiple value definitions to the repository
+ * @param def
+ * @throws DataTypeSyntaxError
+ */
+ public void addValueDefinitions(String def) throws DataTypeSyntaxError {
+ try {
+ addValueDefinitions(new DataParser(new StringReader(def)).valueDefinitions());
+ } catch (TokenMgrError e) {
+ throw new DataTypeSyntaxError(e);
+ } catch (ParseException e) {
+ throw new DataTypeSyntaxError(e);
+ }
+ }
+
+ public DataTypeRepository getTypeRepository() {
+ return typeRepository;
+ }
+
+ public void setTypeRepository(DataTypeRepository typeRepository) {
+ this.typeRepository = typeRepository;
+ }
+
+ public BindingScheme getBindingScheme() {
+ return bindingScheme;
+ }
+
+ public void setBindingScheme(BindingScheme bindingScheme) {
+ this.bindingScheme = bindingScheme;
+ }
+
+ /**
+ * Print the content part of a data value. This excludes the name and type of the value.
+ *
+ * @param valueName
+ * @return value or null
if value doesn't exist
+ * @throws BindingException
+ * @throws IOException
+ */
+ public String printValue(String valueName) throws IOException, BindingException {
+ MutableVariant value = get(valueName);
+ if (value==null) return null;
+ StringBuilder sb = new StringBuilder();
+ DataValuePrinter vp = new DataValuePrinter(sb, this);
+ vp.print(value);
+ return sb.toString();
+ }
+
+ /**
+ * Print the whole value repository
+ *
+ * @param sb
+ * @throws IOException
+ * @throws BindingException
+ */
+ public void print(StringBuilder sb)
+ throws IOException, BindingException
+ {
+ DataValuePrinter vp = new DataValuePrinter(sb, this);
+ vp.setFormat( PrintFormat.SINGLE_LINE );
+ DataTypePrinter tp = new DataTypePrinter( sb );
+ tp.setLinefeed( false );
+
+ for (Entry e : values.entrySet()) {
+ String name = e.getKey();
+ MutableVariant value = e.getValue();
+ Datatype type = value.type();
+ sb.append( name+" : " );
+ tp.print(type);
+ sb.append( " = " );
+ vp.print(value);
+ sb.append("\n");
+ }
+ }
+
+ /**
+ * Print the whole data value repository as a single multiline string
+ *
+ * @throws RuntimeBindingException
+ * @throws {@link RuntimeIOException}
+ */
+ @Override
+ public String toString() {
+ try {
+ StringBuilder sb = new StringBuilder();
+ print(sb);
+ return sb.toString();
+ } catch (BindingException e) {
+ throw new RuntimeBindingException(e);
+ } catch (IOException e) {
+ throw new RuntimeIOException(e);
+ }
+ }
+
+ /**
+ * Gives a data type to a value heuristically.
+ */
+ public Datatype guessDataType(AstValue value) throws DataTypeSyntaxError {
+ return value.accept(guessDataType);
+ }
+
+ /**
+ * Gives a data type to a value heuristically.
+ */
+ public Datatype guessDataType(String value) throws DataTypeSyntaxError {
+ try {
+ return guessDataType(new DataParser(new StringReader(value)).value());
+ } catch (TokenMgrError e) {
+ throw new DataTypeSyntaxError(e);
+ } catch (ParseException e) {
+ throw new DataTypeSyntaxError(e);
+ }
+ }
+
+ class ValueTranslator implements Binding.Visitor {
+
+ AstValue value;
+
+ public ValueTranslator(AstValue value) {
+ this.value = value;
+ }
+
+ private ValueTranslationRuntimeException typeError(Binding expectedType, AstValue actualValue) {
+ throw new ValueTranslationRuntimeException("Expected " + expectedType.type().toSingleLineString() +
+ " but got " + actualValue.getClass().getSimpleName() + ".");
+ }
+
+ @Override
+ public Object visit(ArrayBinding b) {
+ if(value instanceof AstArray) {
+ AstArray array = (AstArray)value;
+ Object[] components = new Object[array.elements.size()];
+ Binding componentBinding = b.getComponentBinding();
+ int i=0;
+ for(AstValue component : array.elements) {
+ value = component;
+ components[i++] = componentBinding.accept(this);
+ }
+ return b.createUnchecked(components);
+ }
+ throw typeError(b, value);
+ }
+
+ @Override
+ public Object visit(BooleanBinding b) {
+ if(value instanceof AstBoolean) {
+ return b.createUnchecked(((AstBoolean)value).value);
+ }
+ throw typeError(b, value);
+ }
+
+ @Override
+ public Object visit(DoubleBinding b) {
+ if(value instanceof AstFloat) {
+ return b.createUnchecked(((AstFloat)value).value);
+ }
+ if(value instanceof AstInteger) {
+ return b.createUnchecked(((AstInteger)value).value);
+ }
+ throw typeError(b, value);
+ }
+
+ @Override
+ public Object visit(FloatBinding b) {
+ if(value instanceof AstFloat) {
+ return b.createUnchecked(((AstFloat)value).value);
+ }
+ if(value instanceof AstInteger) {
+ return b.createUnchecked(((AstInteger)value).value);
+ }
+ throw typeError(b, value);
+ }
+
+ @Override
+ public Object visit(IntegerBinding b) {
+ if(value instanceof AstInteger) {
+ return b.createUnchecked(((AstInteger)value).value);
+ }
+ throw typeError(b, value);
+ }
+
+ @Override
+ public Object visit(ByteBinding b) {
+ if(value instanceof AstInteger) {
+ return b.createUnchecked(((AstInteger)value).value);
+ }
+ throw typeError(b, value);
+ }
+
+ @Override
+ public Object visit(LongBinding b) {
+ if(value instanceof AstInteger) {
+ return b.createUnchecked(((AstInteger)value).value);
+ }
+ throw typeError(b, value);
+ }
+
+ @Override
+ public Object visit(OptionalBinding b) {
+ if(value == AstNull.NULL)
+ return b.createNoValueUnchecked();
+ else
+ return b.createValueUnchecked(b.getComponentBinding().accept(this));
+ }
+
+ @Override
+ public Object visit(RecordBinding b) {
+ if(value instanceof AstRecord) {
+ AstRecord record = (AstRecord)value;
+ Object[] components = new Object[b.getComponentCount()];
+ boolean[] assigned = new boolean[b.getComponentCount()];
+ for(AstComponentAssignment assignment : record.components) {
+ value = assignment.value;
+ Integer index = b.type().getComponentIndex(assignment.component);
+ if(index == null)
+ throw new ValueTranslationRuntimeException("Invalid record component " + assignment.component + ".");
+ components[index] = b.getComponentBinding(index).accept(this);
+ assigned[index] = true;
+ }
+ for(int i=0;i guessDataType = new AstValueVisitor() {
+
+ @Override
+ public Datatype visit(AstArray astArray) {
+ if(astArray.elements.isEmpty())
+ throw new ValueTranslationRuntimeException("Cannot guess the data type of empty array.");
+ return astArray.elements.get(0).accept(this);
+ }
+
+ @Override
+ public Datatype visit(AstBoolean astBoolean) {
+ return Datatypes.BOOLEAN;
+ }
+
+ @Override
+ public Datatype visit(AstFloat astFloat) {
+ return Datatypes.DOUBLE;
+ }
+
+ @Override
+ public Datatype visit(AstInteger astInteger) {
+ return Datatypes.INTEGER;
+ }
+
+ @Override
+ public Datatype visit(AstMap astMap) {
+ if(astMap.components.isEmpty())
+ throw new ValueTranslationRuntimeException("Cannot guess the data type of empty map.");
+ AstMapAssignment assignment = astMap.components.get(0);
+ return new MapType(assignment.key.accept(this), assignment.value.accept(this));
+ }
+
+ @Override
+ public Datatype visit(AstNull astNull) {
+ throw new ValueTranslationRuntimeException("Cannot guess the data type");
+ }
+
+ @Override
+ public Datatype visit(AstRecord astRecord) {
+ Component[] components = new Component[astRecord.components.size()];
+ int i = 0;
+ for(AstComponentAssignment assignment : astRecord.components) {
+ components[i++] = new Component(
+ assignment.component,
+ assignment.value.accept(this)
+ );
+ }
+ return new RecordType(false, components);
+ }
+
+ @Override
+ public Datatype visit(AstReference astReference) {
+ MutableVariant v = get(astReference.name);
+ if(v == null)
+ throw new ValueTranslationRuntimeException("Undefined reference to " + astReference.name + ".");
+ return v.type();
+ }
+
+ @Override
+ public Datatype visit(AstString astString) {
+ return Datatypes.STRING;
+ }
+
+ @Override
+ public Datatype visit(AstTaggedValue astTaggedValue) {
+ // Guessed datatype would be a union with just one component. Not very useful.
+ throw new ValueTranslationRuntimeException("Cannot guess the data type of tagged value");
+ }
+
+ @Override
+ public Datatype visit(AstTuple astTuple) {
+ Component[] components = new Component[astTuple.elements.size()];
+ int i = 0;
+ for(AstValue value : astTuple.elements) {
+ components[i] = new Component(
+ Integer.toString(i),
+ value.accept(this)
+ );
+ ++i;
+ }
+ return new RecordType(false, components);
+ }
+
+ @Override
+ public Datatype visit(AstVariant astVariant) {
+ return Datatypes.VARIANT;
+ }
+ };
+
+
+}