-/*******************************************************************************\r
- * Copyright (c) 2010- Association for Decentralized Information Management in\r
- * Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- * \r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.databoard.binding.impl;\r
-\r
-import java.io.IOException;\r
-import java.nio.ByteBuffer;\r
-import java.util.Set;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.Datatypes;\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.binding.IntegerBinding;\r
-import org.simantics.databoard.binding.LongBinding;\r
-import org.simantics.databoard.binding.StringBinding;\r
-import org.simantics.databoard.binding.VariantBinding;\r
-import org.simantics.databoard.binding.error.BindingException;\r
-import org.simantics.databoard.binding.mutable.MutableVariant;\r
-import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;\r
-import org.simantics.databoard.serialization.Serializer;\r
-import org.simantics.databoard.serialization.SerializerConstructionException;\r
-import org.simantics.databoard.serialization.SerializerFactory;\r
-import org.simantics.databoard.type.Datatype;\r
-import org.simantics.databoard.util.Base64;\r
-import org.simantics.databoard.util.URIUtil;\r
-import org.simantics.databoard.util.binary.BinaryMemory;\r
-import org.simantics.databoard.util.binary.BinaryReadable;\r
-\r
-/**\r
- * This class binding Variant to a filename/URL compatible String.\r
- * The value is human-readable for strings, integers and longs. \r
- * For datatypes the value is Base64 encoded binary.\r
- * \r
- * Filenames have the following encoding:\r
- * S<string> String types, if string doesn't have the following \r
- * control characters " : < > | ? * # \ / % [0..31] [128..] are escaped with %<hex><hex>\r
- * I<integer> Integer types\r
- * L<long> Long types\r
- * B<base64> All other cases. The value is binary encoded and presented as single line Base64 string.\r
- * Base64 encoding has url and filename safe options enabled. \r
- *\r
- * See StringVariantBindingExample\r
- * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
- */\r
-public class StringVariantBinding extends VariantBinding {\r
- \r
- SerializerFactory serializationFactory;\r
- VariantBinding variantBinding;\r
- \r
- public StringVariantBinding(SerializerFactory serializationFactory, VariantBinding variantBinding) {\r
- this.serializationFactory = serializationFactory;\r
- this.variantBinding = variantBinding;\r
- }\r
- \r
- @Override\r
- public Object create(Binding binding, Object value) throws BindingException {\r
- if (binding instanceof StringBinding && binding.type().equals(Datatypes.STRING)) {\r
- StringBinding sb = (StringBinding) binding;\r
- return "S"+URIUtil.encodeURI( sb.getValue(value) );\r
- }\r
- \r
- if (binding instanceof IntegerBinding && binding.type().equals(Datatypes.INTEGER)) {\r
- IntegerBinding ib = (IntegerBinding) binding;\r
- return "I"+ib.getValue_(value);\r
- }\r
- \r
- if (binding instanceof LongBinding && binding.type().equals(Datatypes.LONG)) {\r
- LongBinding lb = (LongBinding) binding;\r
- return "L"+lb.getValue_(value);\r
- }\r
- \r
- try {\r
- MutableVariant v = new MutableVariant(binding, value);\r
- byte[] data = serializationFactory.getSerializerUnchecked( variantBinding ).serialize(v);\r
- return "B"+Base64.encodeBytes(data, Base64.URL_SAFE);\r
- } catch (RuntimeSerializerConstructionException e) {\r
- throw new BindingException(e);\r
- } catch (IOException e) {\r
- throw new BindingException(e);\r
- }\r
- }\r
-\r
- @Override\r
- public Binding getContentBinding(Object variant) throws BindingException {\r
- String str = (String) variant;\r
- if (str.startsWith("S")) {\r
- return Bindings.STRING;\r
- }\r
- if (str.startsWith("I")) {\r
- return Bindings.INTEGER;\r
- }\r
- if (str.startsWith("L")) {\r
- return Bindings.LONG;\r
- }\r
- if (str.startsWith("B")) {\r
- try {\r
- byte[] data = Base64.decode(str.substring(1), Base64.URL_SAFE);\r
- BinaryReadable readable = new BinaryMemory( ByteBuffer.wrap(data) ) ;\r
- Datatype type = (Datatype) getDatatypeSerializer().deserialize(readable);\r
- return Bindings.getMutableBinding(type);\r
- } catch (IOException e) {\r
- throw new BindingException(e);\r
- } \r
- }\r
- \r
- throw new BindingException("Invalid string");\r
- }\r
-\r
- @Override\r
- public Datatype getContentType(Object variant) throws BindingException {\r
- String str = (String) variant;\r
- if (str.startsWith("S")) {\r
- return Bindings.STRING.type();\r
- }\r
- if (str.startsWith("I")) {\r
- return Bindings.INTEGER.type();\r
- }\r
- if (str.startsWith("L")) {\r
- return Bindings.LONG.type();\r
- }\r
- if (str.startsWith("B")) {\r
- try {\r
- byte[] data = Base64.decode(str.substring(1), Base64.URL_SAFE);\r
- BinaryReadable readable = new BinaryMemory( ByteBuffer.wrap(data) ) ;\r
- return (Datatype) getDatatypeSerializer().deserialize(readable);\r
- } catch (IOException e) {\r
- throw new BindingException(e);\r
- } \r
- }\r
- \r
- throw new BindingException("Invalid string");\r
- }\r
-\r
- @Override\r
- public Object getContent(Object obj, Binding binding)\r
- throws BindingException {\r
- if (obj==null) throw new BindingException("null value is not Variant");\r
- if (obj instanceof String == false) throw new BindingException("wrong class, String expected");\r
- \r
- String str = (String) obj;\r
- \r
- if (str.startsWith("S")) {\r
- if (binding instanceof StringBinding == false) throw new BindingException("StringBinding expected, got "+binding.getClass().getSimpleName());\r
- String value = URIUtil.decodeURI( str.substring(1) );\r
- StringBinding sb = (StringBinding) binding;\r
- return sb.create(value);\r
- }\r
- \r
- if (str.startsWith("I")) {\r
- if (binding instanceof IntegerBinding == false) throw new BindingException("IntegerBinding expected, got "+binding.getClass().getSimpleName());\r
- try {\r
- Integer value = Integer.valueOf( str.substring(1) );\r
- IntegerBinding ib = (IntegerBinding) binding;\r
- return ib.create(value); \r
- } catch (NumberFormatException nfe) {\r
- throw new BindingException(nfe);\r
- }\r
- }\r
-\r
- if (str.startsWith("L")) {\r
- if (binding instanceof LongBinding == false) throw new BindingException("LongBinding expected, got "+binding.getClass().getSimpleName());\r
- try {\r
- Long value = Long.valueOf( str.substring(1) );\r
- LongBinding lb = (LongBinding) binding;\r
- return lb.create(value); \r
- } catch (NumberFormatException nfe) {\r
- throw new BindingException(nfe);\r
- }\r
- }\r
- \r
- if (str.startsWith("B")) {\r
- try {\r
- byte[] data = Base64.decode(str.substring(1), Base64.URL_SAFE);\r
- BinaryReadable readable = new BinaryMemory( ByteBuffer.wrap(data) ) ;\r
- Datatype type = (Datatype) getDatatypeSerializer().deserialize(readable);\r
- if (!type.equals(binding.type()))\r
- throw new BindingException("Binding for "+type.toSingleLineString()+" expected, but got "+binding.type());\r
- return Bindings.getSerializer( binding ).deserialize(readable);\r
- } catch (IOException ioe) {\r
- throw new BindingException(ioe);\r
- } catch (RuntimeSerializerConstructionException e) {\r
- throw new BindingException(e);\r
- } catch (SerializerConstructionException e) {\r
- throw new BindingException(e);\r
- }\r
- }\r
- \r
- throw new BindingException("Invalid value"); \r
- }\r
-\r
- @Override\r
- public Object getContent(Object obj) throws BindingException {\r
- if (obj==null) throw new BindingException("null value is not Variant");\r
- if (obj instanceof String == false) throw new BindingException("wrong class, String expected");\r
- \r
- String str = (String) obj;\r
- \r
- if (str.startsWith("S")) {\r
- /*String value =*/ URIUtil.decodeURI( str.substring(1) ); \r
- return Bindings.STRING;\r
- }\r
- \r
- if (str.startsWith("I")) {\r
- try {\r
- /*Integer value =*/ Integer.valueOf( str.substring(1) );\r
- return Bindings.INTEGER; \r
- } catch (NumberFormatException nfe) {\r
- throw new BindingException(nfe);\r
- }\r
- }\r
-\r
- if (str.startsWith("L")) {\r
- try {\r
- /*Long value =*/ Long.valueOf( str.substring(1) );\r
- return Bindings.LONG; \r
- } catch (NumberFormatException nfe) {\r
- throw new BindingException(nfe);\r
- }\r
- }\r
- \r
- if (str.startsWith("B")) {\r
- try {\r
- byte[] data = Base64.decode(str.substring(1), Base64.URL_SAFE);\r
- BinaryReadable readable = new BinaryMemory( ByteBuffer.wrap(data) );\r
- MutableVariant variant = (MutableVariant) Bindings.getSerializerUnchecked( Bindings.MUTABLE_VARIANT).deserialize(readable);\r
- return variant.getValue();\r
- } catch (IOException ioe) {\r
- throw new BindingException(ioe);\r
- } catch (RuntimeSerializerConstructionException e) {\r
- throw new BindingException(e);\r
- }\r
- }\r
- \r
- throw new BindingException("Invalid value"); \r
- }\r
-\r
- @Override\r
- public void setContent(Object variant, Binding binding, Object value)\r
- throws BindingException {\r
- throw new BindingException("Cannot set value to an immutable String");\r
- }\r
-\r
- @Override\r
- public void assertInstaceIsValid(Object obj, Set<Object> validInstances)\r
- throws BindingException {\r
- if (obj==null) throw new BindingException("null value is not Variant");\r
- if (obj instanceof String == false) throw new BindingException("wrong class, String expected");\r
- Object value = getContent(obj);\r
- Binding binding = getContentBinding(obj);\r
- binding.assertInstaceIsValid(value);\r
- }\r
-\r
- @Override\r
- public boolean isInstance(Object obj) { \r
- return obj instanceof String;\r
- }\r
-\r
- static Serializer DATATYPE_SERIALIZER; \r
- static Serializer getDatatypeSerializer()\r
- {\r
- if (DATATYPE_SERIALIZER == null) DATATYPE_SERIALIZER = Bindings.getSerializerUnchecked( Bindings.getBindingUnchecked(Datatype.class) );\r
- return DATATYPE_SERIALIZER;\r
- }\r
-\r
- @Override\r
- protected boolean baseEquals(Object obj) {\r
- StringVariantBinding o = (StringVariantBinding)obj;\r
- return super.baseEquals(obj) && o.serializationFactory == serializationFactory && o.variantBinding == variantBinding;\r
- }\r
-}\r
+/*******************************************************************************
+ * 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.binding.impl;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Set;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.Datatypes;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.IntegerBinding;
+import org.simantics.databoard.binding.LongBinding;
+import org.simantics.databoard.binding.StringBinding;
+import org.simantics.databoard.binding.VariantBinding;
+import org.simantics.databoard.binding.error.BindingException;
+import org.simantics.databoard.binding.mutable.MutableVariant;
+import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
+import org.simantics.databoard.serialization.Serializer;
+import org.simantics.databoard.serialization.SerializerConstructionException;
+import org.simantics.databoard.serialization.SerializerScheme;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.databoard.util.Base64;
+import org.simantics.databoard.util.URIUtil;
+import org.simantics.databoard.util.binary.BinaryMemory;
+import org.simantics.databoard.util.binary.BinaryReadable;
+
+/**
+ * This class binding Variant to a filename/URL compatible String.
+ * The value is human-readable for strings, integers and longs.
+ * For datatypes the value is Base64 encoded binary.
+ *
+ * Filenames have the following encoding:
+ * S<string> String types, if string doesn't have the following
+ * control characters " : < > | ? * # \ / % [0..31] [128..] are escaped with %<hex><hex>
+ * I<integer> Integer types
+ * L<long> Long types
+ * B<base64> All other cases. The value is binary encoded and presented as single line Base64 string.
+ * Base64 encoding has url and filename safe options enabled.
+ *
+ * See StringVariantBindingExample
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
+ */
+public class StringVariantBinding extends VariantBinding {
+
+ SerializerScheme serializationFactory;
+ VariantBinding variantBinding;
+
+ public StringVariantBinding(SerializerScheme serializationFactory, VariantBinding variantBinding) {
+ this.serializationFactory = serializationFactory;
+ this.variantBinding = variantBinding;
+ }
+
+ @Override
+ public Object create(Binding binding, Object value) throws BindingException {
+ if (binding instanceof StringBinding && binding.type().equals(Datatypes.STRING)) {
+ StringBinding sb = (StringBinding) binding;
+ return "S"+URIUtil.encodeURI( sb.getValue(value) );
+ }
+
+ if (binding instanceof IntegerBinding && binding.type().equals(Datatypes.INTEGER)) {
+ IntegerBinding ib = (IntegerBinding) binding;
+ return "I"+ib.getValue_(value);
+ }
+
+ if (binding instanceof LongBinding && binding.type().equals(Datatypes.LONG)) {
+ LongBinding lb = (LongBinding) binding;
+ return "L"+lb.getValue_(value);
+ }
+
+ try {
+ MutableVariant v = new MutableVariant(binding, value);
+ byte[] data = serializationFactory.getSerializerUnchecked( variantBinding ).serialize(v);
+ return "B"+Base64.encodeBytes(data, Base64.URL_SAFE);
+ } catch (RuntimeSerializerConstructionException e) {
+ throw new BindingException(e);
+ } catch (IOException e) {
+ throw new BindingException(e);
+ }
+ }
+
+ @Override
+ public Binding getContentBinding(Object variant) throws BindingException {
+ String str = (String) variant;
+ if (str.startsWith("S")) {
+ return Bindings.STRING;
+ }
+ if (str.startsWith("I")) {
+ return Bindings.INTEGER;
+ }
+ if (str.startsWith("L")) {
+ return Bindings.LONG;
+ }
+ if (str.startsWith("B")) {
+ try {
+ byte[] data = Base64.decode(str.substring(1), Base64.URL_SAFE);
+ BinaryReadable readable = new BinaryMemory( ByteBuffer.wrap(data) ) ;
+ Datatype type = (Datatype) getDatatypeSerializer().deserialize(readable);
+ return Bindings.getMutableBinding(type);
+ } catch (IOException e) {
+ throw new BindingException(e);
+ }
+ }
+
+ throw new BindingException("Invalid string");
+ }
+
+ @Override
+ public Datatype getContentType(Object variant) throws BindingException {
+ String str = (String) variant;
+ if (str.startsWith("S")) {
+ return Bindings.STRING.type();
+ }
+ if (str.startsWith("I")) {
+ return Bindings.INTEGER.type();
+ }
+ if (str.startsWith("L")) {
+ return Bindings.LONG.type();
+ }
+ if (str.startsWith("B")) {
+ try {
+ byte[] data = Base64.decode(str.substring(1), Base64.URL_SAFE);
+ BinaryReadable readable = new BinaryMemory( ByteBuffer.wrap(data) ) ;
+ return (Datatype) getDatatypeSerializer().deserialize(readable);
+ } catch (IOException e) {
+ throw new BindingException(e);
+ }
+ }
+
+ throw new BindingException("Invalid string");
+ }
+
+ @Override
+ public Object getContent(Object obj, Binding binding)
+ throws BindingException {
+ if (obj==null) throw new BindingException("null value is not Variant");
+ if (obj instanceof String == false) throw new BindingException("wrong class, String expected");
+
+ String str = (String) obj;
+
+ if (str.startsWith("S")) {
+ if (binding instanceof StringBinding == false) throw new BindingException("StringBinding expected, got "+binding.getClass().getSimpleName());
+ String value = URIUtil.decodeURI( str.substring(1) );
+ StringBinding sb = (StringBinding) binding;
+ return sb.create(value);
+ }
+
+ if (str.startsWith("I")) {
+ if (binding instanceof IntegerBinding == false) throw new BindingException("IntegerBinding expected, got "+binding.getClass().getSimpleName());
+ try {
+ Integer value = Integer.valueOf( str.substring(1) );
+ IntegerBinding ib = (IntegerBinding) binding;
+ return ib.create(value);
+ } catch (NumberFormatException nfe) {
+ throw new BindingException(nfe);
+ }
+ }
+
+ if (str.startsWith("L")) {
+ if (binding instanceof LongBinding == false) throw new BindingException("LongBinding expected, got "+binding.getClass().getSimpleName());
+ try {
+ Long value = Long.valueOf( str.substring(1) );
+ LongBinding lb = (LongBinding) binding;
+ return lb.create(value);
+ } catch (NumberFormatException nfe) {
+ throw new BindingException(nfe);
+ }
+ }
+
+ if (str.startsWith("B")) {
+ try {
+ byte[] data = Base64.decode(str.substring(1), Base64.URL_SAFE);
+ BinaryReadable readable = new BinaryMemory( ByteBuffer.wrap(data) ) ;
+ Datatype type = (Datatype) getDatatypeSerializer().deserialize(readable);
+ if (!type.equals(binding.type()))
+ throw new BindingException("Binding for "+type.toSingleLineString()+" expected, but got "+binding.type());
+ return Bindings.getSerializer( binding ).deserialize(readable);
+ } catch (IOException ioe) {
+ throw new BindingException(ioe);
+ } catch (RuntimeSerializerConstructionException e) {
+ throw new BindingException(e);
+ } catch (SerializerConstructionException e) {
+ throw new BindingException(e);
+ }
+ }
+
+ throw new BindingException("Invalid value");
+ }
+
+ @Override
+ public Object getContent(Object obj) throws BindingException {
+ if (obj==null) throw new BindingException("null value is not Variant");
+ if (obj instanceof String == false) throw new BindingException("wrong class, String expected");
+
+ String str = (String) obj;
+
+ if (str.startsWith("S")) {
+ /*String value =*/ URIUtil.decodeURI( str.substring(1) );
+ return Bindings.STRING;
+ }
+
+ if (str.startsWith("I")) {
+ try {
+ /*Integer value =*/ Integer.valueOf( str.substring(1) );
+ return Bindings.INTEGER;
+ } catch (NumberFormatException nfe) {
+ throw new BindingException(nfe);
+ }
+ }
+
+ if (str.startsWith("L")) {
+ try {
+ /*Long value =*/ Long.valueOf( str.substring(1) );
+ return Bindings.LONG;
+ } catch (NumberFormatException nfe) {
+ throw new BindingException(nfe);
+ }
+ }
+
+ if (str.startsWith("B")) {
+ try {
+ byte[] data = Base64.decode(str.substring(1), Base64.URL_SAFE);
+ BinaryReadable readable = new BinaryMemory( ByteBuffer.wrap(data) );
+ MutableVariant variant = (MutableVariant) Bindings.getSerializerUnchecked( Bindings.MUTABLE_VARIANT).deserialize(readable);
+ return variant.getValue();
+ } catch (IOException ioe) {
+ throw new BindingException(ioe);
+ } catch (RuntimeSerializerConstructionException e) {
+ throw new BindingException(e);
+ }
+ }
+
+ throw new BindingException("Invalid value");
+ }
+
+ @Override
+ public void setContent(Object variant, Binding binding, Object value)
+ throws BindingException {
+ throw new BindingException("Cannot set value to an immutable String");
+ }
+
+ @Override
+ public void assertInstaceIsValid(Object obj, Set<Object> validInstances)
+ throws BindingException {
+ if (obj==null) throw new BindingException("null value is not Variant");
+ if (obj instanceof String == false) throw new BindingException("wrong class, String expected");
+ Object value = getContent(obj);
+ Binding binding = getContentBinding(obj);
+ binding.assertInstaceIsValid(value);
+ }
+
+ @Override
+ public boolean isInstance(Object obj) {
+ return obj instanceof String;
+ }
+
+ static Serializer DATATYPE_SERIALIZER;
+ static Serializer getDatatypeSerializer()
+ {
+ if (DATATYPE_SERIALIZER == null) DATATYPE_SERIALIZER = Bindings.getSerializerUnchecked( Bindings.getBindingUnchecked(Datatype.class) );
+ return DATATYPE_SERIALIZER;
+ }
+
+ @Override
+ protected boolean baseEquals(Object obj) {
+ StringVariantBinding o = (StringVariantBinding)obj;
+ return super.baseEquals(obj) && o.serializationFactory == serializationFactory && o.variantBinding == variantBinding;
+ }
+}