]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.databoard/src/org/simantics/databoard/binding/impl/StringVariantBinding.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / binding / impl / StringVariantBinding.java
diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/impl/StringVariantBinding.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/impl/StringVariantBinding.java
new file mode 100644 (file)
index 0000000..e233aa0
--- /dev/null
@@ -0,0 +1,278 @@
+/*******************************************************************************\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