From: Reino Ruusu Date: Tue, 8 Sep 2020 14:45:29 +0000 (+0300) Subject: Updating of component properties when type code changes X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=140777cbd6d770435d8eb70f9e2266e5e849658e;p=simantics%2Fdistrict.git Updating of component properties when type code changes gitlab #93 Change-Id: Ia5ac3f513adfd57d4a2e499c9a7dd4ef77355e9f --- diff --git a/org.simantics.district.network.ontology/graph/DistrictNetworkTechType.pgraph b/org.simantics.district.network.ontology/graph/DistrictNetworkTechType.pgraph index adebe013..96865b34 100644 --- a/org.simantics.district.network.ontology/graph/DistrictNetworkTechType.pgraph +++ b/org.simantics.district.network.ontology/graph/DistrictNetworkTechType.pgraph @@ -1,5 +1,6 @@ L0 = STR = +SEL = DN = @@ -13,3 +14,10 @@ table = TT.TechTypeTable -- table.HasComponentType STR.ComponentType + +TT.Functions : L0.Library +TT.Functions.techTypeCodeValueAccessor : L0.ExternalValue + L0.HasValueType "ValueAccessor" + +TT.TechTypeCodeParameterType : SEL.GenericParameterType + @L0.assert L0.valueAccessor TT.Functions.techTypeCodeValueAccessor diff --git a/org.simantics.district.network.ontology/src/org/simantics/district/network/ontology/DistrictNetworkResource.java b/org.simantics.district.network.ontology/src/org/simantics/district/network/ontology/DistrictNetworkResource.java index e6a31a53..83124c1e 100644 --- a/org.simantics.district.network.ontology/src/org/simantics/district/network/ontology/DistrictNetworkResource.java +++ b/org.simantics.district.network.ontology/src/org/simantics/district/network/ontology/DistrictNetworkResource.java @@ -380,6 +380,9 @@ public class DistrictNetworkResource { public final Resource SupplyInConnectionType; public final Resource SupplyOutConnectionType; public final Resource TechType; + public final Resource TechType_Functions; + public final Resource TechType_Functions_techTypeCodeValueAccessor; + public final Resource TechType_TechTypeCodeParameterType; public final Resource TechType_TechTypeTable; public final Resource TechType_TechTypeTable_HasComponentType; public final Resource TechType_TechTypeTable_HasData; @@ -839,6 +842,9 @@ public class DistrictNetworkResource { public static final String SupplyInConnectionType = "http://www.simantics.org/DistrictNetwork-1.0/SupplyInConnectionType"; public static final String SupplyOutConnectionType = "http://www.simantics.org/DistrictNetwork-1.0/SupplyOutConnectionType"; public static final String TechType = "http://www.simantics.org/DistrictNetwork-1.0/TechType"; + public static final String TechType_Functions = "http://www.simantics.org/DistrictNetwork-1.0/TechType/Functions"; + public static final String TechType_Functions_techTypeCodeValueAccessor = "http://www.simantics.org/DistrictNetwork-1.0/TechType/Functions/techTypeCodeValueAccessor"; + public static final String TechType_TechTypeCodeParameterType = "http://www.simantics.org/DistrictNetwork-1.0/TechType/TechTypeCodeParameterType"; public static final String TechType_TechTypeTable = "http://www.simantics.org/DistrictNetwork-1.0/TechType/TechTypeTable"; public static final String TechType_TechTypeTable_HasComponentType = "http://www.simantics.org/DistrictNetwork-1.0/TechType/TechTypeTable/HasComponentType"; public static final String TechType_TechTypeTable_HasData = "http://www.simantics.org/DistrictNetwork-1.0/TechType/TechTypeTable/HasData"; @@ -1308,6 +1314,9 @@ public class DistrictNetworkResource { SupplyInConnectionType = getResourceOrNull(graph, URIs.SupplyInConnectionType); SupplyOutConnectionType = getResourceOrNull(graph, URIs.SupplyOutConnectionType); TechType = getResourceOrNull(graph, URIs.TechType); + TechType_Functions = getResourceOrNull(graph, URIs.TechType_Functions); + TechType_Functions_techTypeCodeValueAccessor = getResourceOrNull(graph, URIs.TechType_Functions_techTypeCodeValueAccessor); + TechType_TechTypeCodeParameterType = getResourceOrNull(graph, URIs.TechType_TechTypeCodeParameterType); TechType_TechTypeTable = getResourceOrNull(graph, URIs.TechType_TechTypeTable); TechType_TechTypeTable_HasComponentType = getResourceOrNull(graph, URIs.TechType_TechTypeTable_HasComponentType); TechType_TechTypeTable_HasData = getResourceOrNull(graph, URIs.TechType_TechTypeTable_HasData); diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/techtype/table/TechTypeTable.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/techtype/table/TechTypeTable.java index f3ba54d9..0c44bff0 100644 --- a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/techtype/table/TechTypeTable.java +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/techtype/table/TechTypeTable.java @@ -44,7 +44,7 @@ import org.eclipse.swt.widgets.Text; import org.simantics.Simantics; import org.simantics.db.Resource; import org.simantics.db.exception.DatabaseException; -import org.simantics.district.network.techtype.requests.WriteTechTypeTableRequest; +import org.simantics.district.network.techtype.requests.WriteTechTypeTable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -203,7 +203,7 @@ public class TechTypeTable extends Composite { } try { - Simantics.getSession().syncRequest(new WriteTechTypeTableRequest(componentType, data)); + Simantics.getSession().syncRequest(new WriteTechTypeTable(componentType, data)); } catch (DatabaseException e) { LOGGER.error("Failed to write tech type table data to model", e); } diff --git a/org.simantics.district.network/META-INF/MANIFEST.MF b/org.simantics.district.network/META-INF/MANIFEST.MF index b2442a89..2ee82502 100644 --- a/org.simantics.district.network/META-INF/MANIFEST.MF +++ b/org.simantics.district.network/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Simantics District Network -Bundle-SymbolicName: org.simantics.district.network +Bundle-SymbolicName: org.simantics.district.network;singleton:=true Bundle-Version: 1.0.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.simantics.db, @@ -21,11 +21,14 @@ Require-Bundle: org.simantics.db, org.simantics.db.indexing, org.simantics.scl.osgi, org.eclipse.collections, - org.simantics.structural.synchronization.client + org.simantics.structural.synchronization.client, + org.apache.commons.csv Export-Package: org.simantics.district.network, org.simantics.district.network.changeset, org.simantics.district.network.profile, + org.simantics.district.network.techtype, org.simantics.district.network.techtype.requests, + org.simantics.district.network.techtype.variable, org.simantics.district.network.visualisations, org.simantics.district.network.visualisations.model, org.simantics.district.network.visualisations.triggers diff --git a/org.simantics.district.network/build.properties b/org.simantics.district.network/build.properties index 21a6c989..1ae7e4e9 100644 --- a/org.simantics.district.network/build.properties +++ b/org.simantics.district.network/build.properties @@ -3,4 +3,5 @@ output.. = bin/ bin.includes = META-INF/,\ .,\ adapters.xml,\ - scl/ + scl/,\ + plugin.xml diff --git a/org.simantics.district.network/plugin.xml b/org.simantics.district.network/plugin.xml new file mode 100644 index 00000000..b8e40a32 --- /dev/null +++ b/org.simantics.district.network/plugin.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/org.simantics.district.network/scl/Simantics/District/TechType.scl b/org.simantics.district.network/scl/Simantics/District/TechType.scl new file mode 100644 index 00000000..9b6ddeb9 --- /dev/null +++ b/org.simantics.district.network/scl/Simantics/District/TechType.scl @@ -0,0 +1,7 @@ +import "Simantics/DB" + +importJava "org.simantics.district.network.techtype.TechTypeUtils" where + "Update component properties from tech type table: `updateComponent component`" + updateComponent :: Resource -> () + "Reset all components to values in a tech type table: `resetComponents table`" + resetComponents :: Resource -> () diff --git a/org.simantics.district.network/src/org/simantics/district/network/techtype/TechTypeUtils.java b/org.simantics.district.network/src/org/simantics/district/network/techtype/TechTypeUtils.java new file mode 100644 index 00000000..7a25ff84 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/techtype/TechTypeUtils.java @@ -0,0 +1,207 @@ +package org.simantics.district.network.techtype; + +import java.util.Collection; +import java.util.Map; + +import org.simantics.Simantics; +import org.simantics.databoard.Bindings; +import org.simantics.databoard.binding.NumberBinding; +import org.simantics.databoard.binding.error.BindingException; +import org.simantics.databoard.type.Datatype; +import org.simantics.databoard.type.NumberType; +import org.simantics.databoard.type.StringType; +import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.procedure.adapter.TransientCacheListener; +import org.simantics.db.common.request.PossibleIndexRoot; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.QueryIndexUtils; +import org.simantics.db.layer0.request.PossibleVariable; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.district.network.ontology.DistrictNetworkResource; +import org.simantics.district.network.techtype.requests.PossibleTechTypeItem; +import org.simantics.district.network.techtype.requests.PossibleTechTypeTable; +import org.simantics.district.network.techtype.requests.TechTypeTableKeyName; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.structural.stubs.StructuralResource2; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TechTypeUtils { + + final static Logger LOGGER = LoggerFactory.getLogger(TechTypeUtils.class); + + public static String DEFAULT_KEY_NAME = "pipeCode"; + + /** + * Execute a cached query for a possible tech type table item in a table with a given item key. + * + * Result is null, if no such item was found. + * + * @param session A request processor on which to run the query + * @param itemCode A key value, such as a pipe code + * @throws DatabaseException + */ + public static Map getTableItem(RequestProcessor session, Resource table, String itemCode) throws DatabaseException { + return session.syncRequest(new PossibleTechTypeItem(table, itemCode), TransientCacheListener.instance()); + } + + /** + * Get a single row in a tech type table for a given item code + * + * Result is null, if no such item was found. + * + * @param table A TechTypeTable resource + * @param itemCode A key value, such as a pipe code + * @return A map from property name to value + * @throws DatabaseException + */ + public static Map getTableItem(Resource table, String itemCode) throws DatabaseException { + Object graph = SCLContext.getCurrent().get("graph"); + if (graph != null && graph instanceof ReadGraph) + return getTableItem((ReadGraph) graph, table, itemCode); + else + return getTableItem(Simantics.getSession(), table, itemCode); + } + + /** + * Reset all components that address the given tech type table to the table values. + * + * @param table A tech type table + * @throws DatabaseException + */ + public static void resetComponents(Resource table) throws DatabaseException { + Simantics.getSession().syncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + Resource model = graph.syncRequest(new PossibleIndexRoot(table), TransientCacheListener.instance()); + if (model == null) + return; + + Resource type = graph.getPossibleObject(table, DistrictNetworkResource.getInstance(graph).TechType_TechTypeTable_HasComponentType); + if (type == null) + return; + + Collection components = QueryIndexUtils.searchByType(graph, model, type); + for (Resource component : components) { + updateComponent(graph, component, table); + } + } + }); + } + + /** + * Update property values of a component based on the values in an associated tech type table, if any + * + * @param graph A write access interface to the graph database + * @param component A structural component + * @throws DatabaseException + */ + public static void updateComponent(WriteGraph graph, Resource component) throws DatabaseException { + StructuralResource2 STR = StructuralResource2.getInstance(graph); + + Resource type = graph.getSingleType(component, STR.Component); + Resource model = graph.syncRequest(new PossibleIndexRoot(component)); + if (model == null) { + LOGGER.info("updateComponent: No model for {}", component); + return; + } + + Resource table = graph.syncRequest(new PossibleTechTypeTable(model, type), TransientCacheListener.instance()); + if (table == null) { + LOGGER.info("updateComponent: No tech type table for {} in {}", type, model); + return; + } + + updateComponent(graph, component, table); + } + + /** + * Update property values of a component based on the values in an associated tech type table, if any + * + * @param component A structural component + * @throws DatabaseException + */ + public static void updateComponent(Resource component) throws DatabaseException { + if (LOGGER.isTraceEnabled()) + LOGGER.trace("updateComponent({})", component); + + Simantics.getSession().syncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + updateComponent(graph, component); + } + }); + } + + /** + * Update a single component's property values to those selected from a tech + * type table + * + * @param graph A write interface to the db + * @param component The component to be updated + * @param table A tech type table + * @throws DatabaseException + */ + public static void updateComponent(WriteGraph graph, Resource component, Resource table) + throws DatabaseException { + if (LOGGER.isTraceEnabled()) + LOGGER.trace("updateComponent(graph, {}, {}), component, table)"); + + Variable v = graph.syncRequest(new PossibleVariable(component)); + if (v == null) { + LOGGER.info("No variable found for {}", component); + return; + } + + String keyProp = getKeyPropertyName(graph, table); + String itemCode = v.getPropertyValue(graph, keyProp); + + Map map = graph.syncRequest(new PossibleTechTypeItem(table, itemCode), TransientCacheListener.instance()); + if (map == null) { + LOGGER.info("No entry found for \"{}\" in tech type table {}", itemCode, table); + return; + } + + for (String key : map.keySet()) { + // Don't write the key property + if (key.equals(DEFAULT_KEY_NAME)) + continue; + + Variable prop = v.getPossibleProperty(graph, key); + if (prop == null) continue; + + Datatype dt = prop.getPossibleDatatype(graph); + if (dt == null) continue; + + String value = map.get(key); + if (dt instanceof NumberType) { + try { + Double num = Double.valueOf(value.replace(",", ".")); + NumberBinding binding = Bindings.getBinding(dt); + prop.setValue(graph, binding.create(num)); + } catch (NumberFormatException e) { + // Revert to asserted value + Resource pred = prop.getPossiblePredicateResource(graph); + if (pred != null) + graph.deny(component, pred); + } catch (BindingException e) { + LOGGER.error("Failed to get binding for datatype {}", dt, e); + } + } else if (dt instanceof StringType) { + prop.setValue(graph, value); + } else { + LOGGER.warn("updateComponent: Unsupported property type {}", dt); + } + } + } + + public static String getKeyPropertyName(ReadGraph graph, Resource table) throws DatabaseException { + String name = graph.syncRequest(new TechTypeTableKeyName(table), TransientCacheListener.instance()); + if (name == null) name = "_" + DEFAULT_KEY_NAME; + return name; + } +} diff --git a/org.simantics.district.network/src/org/simantics/district/network/techtype/requests/PossibleTechTypeItem.java b/org.simantics.district.network/src/org/simantics/district/network/techtype/requests/PossibleTechTypeItem.java new file mode 100644 index 00000000..05e43087 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/techtype/requests/PossibleTechTypeItem.java @@ -0,0 +1,30 @@ +package org.simantics.district.network.techtype.requests; + +import java.util.Map; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.procedure.adapter.TransientCacheListener; +import org.simantics.db.common.request.BinaryRead; +import org.simantics.db.exception.DatabaseException; + +/** + * Query for a possible tech type table item in a table with a given item key. + * + * Results in null, if no such item was found. + */ +public class PossibleTechTypeItem extends BinaryRead> { + + public PossibleTechTypeItem(Resource table, String itemCode) { + super(table, itemCode); + } + + @Override + public Map perform(ReadGraph graph) throws DatabaseException { + Resource table = this.parameter; + String itemCode = this.parameter2; + + Map> map = graph.syncRequest(new TechTypeTableData(table), TransientCacheListener.instance()); + return map.get(itemCode); + } +} \ No newline at end of file diff --git a/org.simantics.district.network/src/org/simantics/district/network/techtype/requests/TechTypeTableData.java b/org.simantics.district.network/src/org/simantics/district/network/techtype/requests/TechTypeTableData.java new file mode 100644 index 00000000..2ff575b7 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/techtype/requests/TechTypeTableData.java @@ -0,0 +1,97 @@ +package org.simantics.district.network.techtype.requests; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ResourceRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.district.network.ontology.DistrictNetworkResource; +import org.simantics.district.network.techtype.TechTypeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TechTypeTableData extends ResourceRead>> { + + private final static Logger LOGGER = LoggerFactory.getLogger(TechTypeTableData.class); + + protected TechTypeTableData(Resource table) { + super(table); + } + + @Override + public Map> perform(ReadGraph graph) throws DatabaseException { + Resource table = this.resource; + + String data = graph.getRelatedValue2(table, + DistrictNetworkResource.getInstance(graph).TechType_TechTypeTable_HasData); + if (data == null) + return Collections.emptyMap(); + + String keyName = TechTypeUtils.getKeyPropertyName(graph, table); + if (keyName.startsWith("_")) + keyName = keyName.substring(1); + + Map> map = new HashMap<>(); + + long ncommas = data.chars().filter(c -> c == ',').count(); + long nsemis = data.chars().filter(c -> c == ';').count(); + char delim = nsemis > ncommas ? ';' : ','; + StringReader reader = new StringReader(data); + + List records = new ArrayList<>(); + try { + CSVFormat format = CSVFormat.newFormat(delim).withQuote('"'); + try (CSVParser parser = format.parse(reader)) { + Iterator it = parser.iterator(); + while (it.hasNext()) { + records.add(it.next()); + } + } + } catch (IOException e) { + LOGGER.error("Error reading CSV data", e); + return Collections.emptyMap(); + } + + CSVRecord header = records.remove(0); + records.remove(0); // Eliminate units row + + int keyIndex = 0; + for (int i = 0; i < header.size(); i++) { + if (header.get(i).equals(keyName)) { + keyIndex = i; + break; + } + } + + for (CSVRecord r : records) { + String key = r.get(keyIndex).intern(); + if (key == null) + continue; + + Map valueMap = new HashMap<>(); + map.put(key, valueMap); + + Iterator h = header.iterator(); + Iterator v = r.iterator(); + + while (h.hasNext() && v.hasNext()) { + String name = h.next().intern(); + String value = v.next(); + valueMap.put(name, value); + } + } + + return map; + } +} \ No newline at end of file diff --git a/org.simantics.district.network/src/org/simantics/district/network/techtype/requests/TechTypeTableKeyName.java b/org.simantics.district.network/src/org/simantics/district/network/techtype/requests/TechTypeTableKeyName.java new file mode 100644 index 00000000..86b7d720 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/techtype/requests/TechTypeTableKeyName.java @@ -0,0 +1,33 @@ +package org.simantics.district.network.techtype.requests; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ResourceRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.district.network.ontology.DistrictNetworkResource; +import org.simantics.layer0.Layer0; + +public class TechTypeTableKeyName extends ResourceRead { + + public TechTypeTableKeyName(Resource table) { + super(table); + } + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + + Resource type = graph.getPossibleObject(resource, DN.TechType_TechTypeTable_HasComponentType); + if (type != null) { + for (Resource r : graph.getObjects(type, L0.DomainOf)) { + Resource accessor = graph.getPossibleObject(r, L0.valueAccessor); + if (accessor.equals(DN.TechType_Functions_techTypeCodeValueAccessor)) { + return graph.getRelatedValue2(r, L0.HasName); + } + } + } + + return null; + } +} \ No newline at end of file diff --git a/org.simantics.district.network/src/org/simantics/district/network/techtype/requests/WriteTechTypeTableRequest.java b/org.simantics.district.network/src/org/simantics/district/network/techtype/requests/WriteTechTypeTable.java similarity index 91% rename from org.simantics.district.network/src/org/simantics/district/network/techtype/requests/WriteTechTypeTableRequest.java rename to org.simantics.district.network/src/org/simantics/district/network/techtype/requests/WriteTechTypeTable.java index 5e6922b8..1f85c5a4 100644 --- a/org.simantics.district.network/src/org/simantics/district/network/techtype/requests/WriteTechTypeTableRequest.java +++ b/org.simantics.district.network/src/org/simantics/district/network/techtype/requests/WriteTechTypeTable.java @@ -12,11 +12,11 @@ import org.simantics.db.layer0.request.PossibleActiveModel; import org.simantics.district.network.ontology.DistrictNetworkResource; import org.simantics.layer0.Layer0; -public final class WriteTechTypeTableRequest extends WriteRequest { +public final class WriteTechTypeTable extends WriteRequest { private final String data; private final Resource componentType; - public WriteTechTypeTableRequest(Resource componentType, String data) { + public WriteTechTypeTable(Resource componentType, String data) { this.data = data; this.componentType = componentType; } diff --git a/org.simantics.district.network/src/org/simantics/district/network/techtype/variable/Functions.java b/org.simantics.district.network/src/org/simantics/district/network/techtype/variable/Functions.java new file mode 100644 index 00000000..beb92684 --- /dev/null +++ b/org.simantics.district.network/src/org/simantics/district/network/techtype/variable/Functions.java @@ -0,0 +1,59 @@ +package org.simantics.district.network.techtype.variable; + +import org.simantics.databoard.binding.Binding; +import org.simantics.databoard.type.Datatype; +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.layer0.variable.ValueAccessor; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.district.network.techtype.TechTypeUtils; +import org.simantics.scl.reflection.annotations.SCLValue; +import org.simantics.structural.stubs.StructuralResource2; + +public class Functions { + @SCLValue(type = "ValueAccessor") + public static final ValueAccessor techTypeCodeValueAccessor = new ValueAccessor() { + + @Override + public Object getValue(ReadGraph graph, Variable context) throws DatabaseException { + return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context); + } + + @Override + public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { + return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context, binding); + } + + @Override + public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException { + org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, value); + + updateComponentProperties(graph, context, value); + } + + @Override + public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) + throws DatabaseException { + org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, value, binding); + + updateComponentProperties(graph, context, value); + } + + @Override + public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException { + return org.simantics.db.layer0.function.All.standardValueAccessor.getDatatype(graph, context); + } + + }; + + protected static void updateComponentProperties(WriteGraph graph, Variable context, Object value) throws DatabaseException { + Variable component = context.getParent(graph); + Resource type = component.getPossibleType(graph, StructuralResource2.getInstance(graph).Component); + if (type == null) + return; + + TechTypeUtils.updateComponent(graph, component.getRepresents(graph)); + } +}