package org.simantics.modeling; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import org.simantics.db.ConverterExternalValue; import org.simantics.db.ExternalValue; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.BinaryRead; import org.simantics.db.common.request.UniqueRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.PropertyInfo; import org.simantics.db.layer0.request.UnescapedPropertyMapOfResource; import org.simantics.db.layer0.variable.ValueAccessor; import org.simantics.db.layer0.variable.Variable; import org.simantics.layer0.Layer0; import org.simantics.scl.runtime.SCLContext; import org.simantics.scl.runtime.function.Function1; import org.simantics.scl.runtime.function.FunctionImpl1; public class ImmutableComponentPropertyContentRequest extends BinaryRead { protected ImmutableComponentPropertyContentRequest(Resource subject, PropertyInfo predicate) { super(subject, predicate); } static class ExcludedSubjects extends UniqueRead> { @Override public Set perform(ReadGraph graph) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); return new HashSet(Arrays.asList(L0.HasName, L0.HasLabel, L0.HasDataType, L0.HasValueType, L0.RequiresValueType, L0.hasStandardResource, L0.RequiresValueType, L0.HasDescription, L0.valueAccessor, L0.domainChildren, L0.domainProperties, L0.classifications, L0.Entity_methods, L0.default_, L0.required, L0.readOnly, L0.valid, L0.validator)); } } public ImmutableComponentPropertyContent getPossibleContent(ReadGraph graph) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); Resource resource = parameter; PropertyInfo pi = parameter2; Resource value = graph.getPossibleObject(resource, pi.predicate); if(value != null) { if(graph.isInstanceOf(value, L0.Literal)) { Object literal = graph.getPossibleValue(value); if(literal != null) { return new ImmutableComponentPropertyContent(pi, value, literal, null); } } else if(graph.isInstanceOf(value, L0.SCLValue)) { Resource converter = graph.getPossibleObject(value, L0.ConvertsToValueWith); if(converter != null) { ExternalValue ev = graph.adapt(converter, ExternalValue.class); if(ev instanceof ConverterExternalValue) { ConverterExternalValue cev = (ConverterExternalValue)ev; Function1 fn = cev.getFunction(graph, resource, value, pi.predicate); return new ImmutableComponentPropertyContent(pi, value, null, fn); } else { System.err.println("Undefined converter " + graph.getURI(converter)); } } } else if(graph.isInstanceOf(value, L0.Value)) { Resource valueAccessor = graph.getPossibleObject(value, L0.valueAccessor); if(valueAccessor != null) { FunctionImpl1 fn = new FunctionImpl1() { @Override public Object apply(Object p0) { try { ReadGraph graph = (ReadGraph)SCLContext.getCurrent().get("graph"); ValueAccessor accessor = graph.getValue2(valueAccessor, p0); return accessor.getValue(graph, (Variable)p0); } catch (DatabaseException e) { throw new IllegalStateException(e); } } }; return new ImmutableComponentPropertyContent(pi, value, null, fn); } } } return null; } private void process(ReadGraph graph, Resource subject, ImmutableComponentPropertyContent result) throws DatabaseException { Set exclusions = graph.syncRequest(new ExcludedSubjects()); if(exclusions.contains(subject)) return; for(PropertyInfo pi : graph.syncRequest(new UnescapedPropertyMapOfResource(subject)).values()) { // This is somewhat awkward if(parameter2.predicate.equals(pi.predicate)) continue; try { if(pi.isHasProperty) { ImmutableComponentPropertyContent pc = graph.syncRequest(new ImmutableComponentPropertyContentRequest(subject, pi)); if(pc != null) { if(result.properties == null) result.properties = new HashMap<>(); result.properties.put(pc.pi.name, pc); } } } catch (DatabaseException e) { e.printStackTrace(); } } } @Override public ImmutableComponentPropertyContent perform(ReadGraph graph) throws DatabaseException { ImmutableComponentPropertyContent result = getPossibleContent(graph); if(result == null) return null; process(graph, result.pi.predicate, result); process(graph, result.valueResource, result); return result; } }