package org.simantics.db.layer0.variable; import org.simantics.databoard.Bindings; import org.simantics.databoard.accessor.reference.ChildReference; import org.simantics.databoard.accessor.reference.IndexReference; import org.simantics.databoard.accessor.reference.NameReference; import org.simantics.databoard.adapter.AdaptException; import org.simantics.databoard.binding.ArrayBinding; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.RecordBinding; import org.simantics.databoard.binding.error.BindingException; import org.simantics.databoard.type.ArrayType; import org.simantics.databoard.type.Datatype; import org.simantics.databoard.type.RecordType; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.RuntimeDatabaseException; public class SubliteralPropertyVariable extends StandardGraphPropertyVariable { private final ChildReference reference; public SubliteralPropertyVariable(ReadGraph graph, Variable parent, Resource predicate, ChildReference reference) throws DatabaseException { super(graph, parent, null, predicate); this.reference = reference; } @Override public Datatype getDatatype(ReadGraph graph) throws DatabaseException { Datatype parentType = parent.getDatatype(graph); if(parentType instanceof ArrayType) { ArrayType at = (ArrayType)parentType; return at.getComponentType(0); } else if(parentType instanceof RecordType) { RecordType rt = (RecordType)parentType; NameReference nr = (NameReference)reference; return rt.getComponent(nr.name).type; } return null; } @SuppressWarnings("unchecked") @Override public T getValue(ReadGraph graph) throws DatabaseException { Object parentValue = parent.getValue(graph); Datatype parentType = parent.getDatatype(graph); Binding parentBinding = Bindings.getBinding(parentType); if (parentType instanceof ArrayType) { ArrayBinding ab = (ArrayBinding)parentBinding; IndexReference ref = (IndexReference)reference; try { return (T)ab.get(parentValue, ref.index); } catch (IndexOutOfBoundsException e) { throw new RuntimeDatabaseException(e); } catch (BindingException e) { throw new RuntimeDatabaseException(e); } } else if (parentType instanceof RecordType) { RecordBinding rb = (RecordBinding)parentBinding; NameReference ref = (NameReference)reference; try { return (T)rb.getComponentObject(parentValue, ref.name); } catch (IndexOutOfBoundsException e) { throw new RuntimeDatabaseException(e); } catch (BindingException e) { throw new RuntimeDatabaseException(e); } } throw new RuntimeDatabaseException("parent variable data type " + parentType + " is not an ArrayType"); } @SuppressWarnings("unchecked") @Override public T getValue(ReadGraph graph, Binding binding) throws DatabaseException { Object parentValue = parent.getValue(graph); Datatype parentType = parent.getDatatype(graph); Binding parentBinding = Bindings.getBinding(parentType); if (parentType instanceof ArrayType) { ArrayBinding ab = (ArrayBinding)parentBinding; IndexReference ref = (IndexReference)reference; try { Object indexValue = ab.get(parentValue, ref.index); return (T) Bindings.adapt(indexValue, ab.getComponentBinding(), binding); } catch (IndexOutOfBoundsException e) { throw new RuntimeDatabaseException(e); } catch (BindingException e) { throw new RuntimeDatabaseException(e); } catch (AdaptException e) { throw new RuntimeDatabaseException(e); } } else if (parentType instanceof RecordType) { RecordBinding rb = (RecordBinding)parentBinding; NameReference ref = (NameReference)reference; try { Object nameValue = (T)rb.getComponentObject(parentValue, ref.name); return (T) Bindings.adapt(nameValue, rb.getComponentBinding(ref.name), binding); } catch (IndexOutOfBoundsException e) { throw new RuntimeDatabaseException(e); } catch (BindingException e) { throw new RuntimeDatabaseException(e); } catch (AdaptException e) { throw new RuntimeDatabaseException(e); } } throw new RuntimeDatabaseException("parent variable data type " + parentType + " is not an ArrayType"); } @Override public void setValue(WriteGraph graph, Object value, Binding binding) throws DatabaseException { Object parentValue = parent.getValue(graph); Datatype parentType = parent.getDatatype(graph); Binding parentBinding = Bindings.getBinding(parentType); if(parentType instanceof ArrayType) { ArrayBinding ab = (ArrayBinding)parentBinding; IndexReference ref = (IndexReference)reference; try { Object copy = parentBinding.clone(parentValue); Object indexValue = Bindings.adapt(value, binding, ab.getComponentBinding()); ab.set(copy, ref.index, indexValue); parent.setValue(graph, copy, parentBinding); } catch (IndexOutOfBoundsException e) { throw new RuntimeDatabaseException(e); } catch (BindingException e) { throw new RuntimeDatabaseException(e); } catch (AdaptException e) { throw new RuntimeDatabaseException(e); } } else if(parentType instanceof RecordType) { RecordBinding rb = (RecordBinding)parentBinding; NameReference ref = (NameReference)reference; try { Object copy = parentBinding.clone(parentValue); Object indexValue = Bindings.adapt(value, binding, rb.getComponentBinding(ref.name)); rb.setComponent(copy, ref.name, indexValue); parent.setValue(graph, copy, parentBinding); } catch (IndexOutOfBoundsException e) { throw new RuntimeDatabaseException(e); } catch (BindingException e) { throw new RuntimeDatabaseException(e); } catch (AdaptException e) { throw new RuntimeDatabaseException(e); } } } @Override public String getName(ReadGraph graph) throws DatabaseException { return reference.toString(true); } @Override public boolean equals(Object obj) { if(!super.equals(obj)) return false; if(!(obj instanceof SubliteralPropertyVariable)) return false; SubliteralPropertyVariable other = (SubliteralPropertyVariable)obj; return reference.equals(other.reference); } @Override public int hashCode() { return super.hashCode() + 31 * reference.hashCode(); } }