]> gerrit.simantics Code Review - simantics/district.git/blobdiff - org.simantics.district.network/src/org/simantics/district/network/techtype/TechTypeUtils.java
Add an SCL interface for loading tech type files
[simantics/district.git] / org.simantics.district.network / src / org / simantics / district / network / techtype / TechTypeUtils.java
index 7a25ff84113586434703da818750dfb901271c18..92eef4fe7f3462ab9afc25a1dd5d43e4808ff3de 100644 (file)
@@ -1,7 +1,14 @@
 package org.simantics.district.network.techtype;
 
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
 import org.simantics.Simantics;
 import org.simantics.databoard.Bindings;
@@ -20,11 +27,16 @@ 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.request.PropertyInfo;
+import org.simantics.db.layer0.request.PropertyInfoRequest;
 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.TechTypeTableData;
 import org.simantics.district.network.techtype.requests.TechTypeTableKeyName;
+import org.simantics.district.network.techtype.requests.WriteTechTypeTable;
+import org.simantics.layer0.Layer0;
 import org.simantics.scl.runtime.SCLContext;
 import org.simantics.structural.stubs.StructuralResource2;
 import org.slf4j.Logger;
@@ -36,6 +48,31 @@ public class TechTypeUtils {
 
        public static String DEFAULT_KEY_NAME = "pipeCode";
 
+       /**
+        * Load a tech type table from a CSV file and write it in the active model.
+        * 
+        * @param componentType  The component type that the tech type table is associated with
+        * @param filePath  A path to a CSV file
+        * @throws DatabaseException
+        * @throws IOException
+        */
+       public static void loadTechTypeTable(Resource componentType, String filePath) throws DatabaseException, IOException {
+               String data;
+               try {
+                       data = Files.lines(Paths.get(filePath), Charset.defaultCharset()).collect(Collectors.joining("\n"));
+               } catch (IOException e) {
+                       LOGGER.error("Failed to read contents of file '{}' as {}", filePath, Charset.defaultCharset(), e);
+                       return;
+               }
+
+               Simantics.getSession().syncRequest(new WriteRequest() {
+                       @Override
+                       public void perform(WriteGraph graph) throws DatabaseException {
+                               graph.syncRequest(new WriteTechTypeTable(componentType, data));
+                       }
+               });
+       }
+       
        /**
         * Execute a cached query for a possible tech type table item in a table with a given item key.
         * 
@@ -93,6 +130,111 @@ public class TechTypeUtils {
                });
        }
        
+       /**
+        * Reset all diagram elements to tech type table values.
+        * 
+        * @param table  A tech type table
+        * @throws DatabaseException
+        */
+       public static void resetMapElements(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;
+                               
+                               DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
+                               Resource type = graph.getPossibleObject(table, DN.TechType_TechTypeTable_HasComponentType);
+                               if (type == null)
+                                       return;
+                               
+                               Layer0 L0 = Layer0.getInstance(graph);
+                               String typeName = graph.getRelatedValue2(type, L0.HasName);
+                               
+                               Resource mapping = null;
+                               for (Resource m : QueryIndexUtils.searchByType(graph, model, DN.Mapping_Base)) {
+                                       String name = graph.getRelatedValue2(m, DN.Mapping_ComponentType);
+                                       if (Objects.equals(name, typeName)) {
+                                               mapping = m;
+                                               break;
+                                       }
+                               }
+                               
+                               if (mapping == null) {
+                                       LOGGER.warn("No mapping found for component type {}", type);
+                                       return;
+                               }
+                               
+                               Map<String, PropertyInfo> properties = new HashMap<>();
+                               Resource mappingType = graph.getSingleType(mapping, DN.Mapping_Base);
+                               Collection<Resource> mappingRelations = graph.getObjects(mappingType, L0.DomainOf);
+                               for (Resource r : mappingRelations) {
+                                       String propertyName = graph.getPossibleRelatedValue2(mapping, r);
+                                       if (propertyName == null)
+                                               continue;
+                                       
+                                       Resource relation = graph.getPossibleObject(r, DN.Mapping_HasPropertyRelation);
+                                       if (relation == null)
+                                               continue;
+                                       
+                                       properties.put(propertyName, graph.syncRequest(new PropertyInfoRequest(relation)));
+                               }
+                               
+                               Map<String, Map<String, String>> data = graph.syncRequest(new TechTypeTableData(table), TransientCacheListener.instance());
+                               String keyName = graph.syncRequest(new TechTypeTableKeyName(table), TransientCacheListener.instance());
+                               Resource keyRelation = properties.get(keyName).predicate;
+                               
+                               if (keyRelation == null) {
+                                       LOGGER.warn("No relation mapped to property {} found in {} mapping", keyName, mapping);
+                                       return;
+                               }
+                               
+                               Resource elementType = graph.isInstanceOf(mapping, DN.Mapping_EdgeMapping) ? DN.Edge :
+                                       graph.isInstanceOf(mapping, DN.Mapping_VertexMapping) ? DN.Vertex :
+                                       DN.Element;
+                               
+                               Collection<Resource> elements = QueryIndexUtils.searchByType(graph, model, elementType);
+                               for (Resource element : elements) {
+                                       Resource elementMapping = graph.getPossibleObject(element, DN.HasMapping);
+                                       if (!mapping.equals(elementMapping))
+                                               continue;
+                                       
+                                       String key = graph.getPossibleRelatedValue2(element, keyRelation);
+                                       Map<String, String> values = data.get(key);
+                                       if (values == null) {
+                                               LOGGER.info("Key {} no found in tech type table {}", key, table);
+                                               continue;
+                                       }
+                                       
+                                       for (Map.Entry<String, String> entry : values.entrySet()) {
+                                               PropertyInfo prop = properties.get(entry.getKey());
+                                               if (prop == null)
+                                                       continue;
+                                               
+                                               String value = entry.getValue();
+                                               Datatype dt = prop.requiredDatatype;
+                                               if (dt instanceof NumberType) {
+                                                       try {
+                                                               Object num = ((NumberBinding)prop.defaultBinding).create(value.replace(",", "."));
+                                                               graph.claimLiteral(element, prop.predicate, prop.literalRange, num, prop.defaultBinding);
+                                                       } catch (NumberFormatException e) {
+                                                               // Revert to asserted value
+                                                               graph.deny(element, prop.predicate);
+                                                       } catch (BindingException e) {
+                                                               LOGGER.error("Failed to get binding for datatype {}", dt, e);
+                                                       }
+                                               } else if (dt instanceof StringType) {
+                                                       graph.claimLiteral(element, prop.predicate, prop.literalRange, value, Bindings.STRING);
+                                               } else {
+                                                       LOGGER.warn("updateComponent: Unsupported property type {}", dt);
+                                               }
+                                       }
+                               }
+                       }
+               });
+       }
+
        /**
         * Update property values of a component based on the values in an associated tech type table, if any
         *