package org.simantics.modeling.subscription; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; import org.simantics.databoard.Bindings; import org.simantics.databoard.Databoard; import org.simantics.databoard.accessor.reference.ChildReference; import org.simantics.databoard.accessor.reference.IndexReference; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.util.URIStringUtils; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; import org.simantics.db.common.request.PossibleIndexRoot; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.exception.PendingVariableException; import org.simantics.db.layer0.request.PossibleVariableValue; import org.simantics.db.layer0.variable.RVI; import org.simantics.db.layer0.variable.Variable; import org.simantics.layer0.Layer0; import org.simantics.modeling.ModelingResources; import org.simantics.utils.datastructures.Pair; import org.simantics.utils.format.FormattingUtils; import org.simantics.utils.format.ValueFormat; public class SubscriptionItemLabel { private static final String NO_VARIABLE_ID = ""; public static String resolveLabel(ReadGraph graph, Resource item, boolean synchronous) throws DatabaseException { IEclipsePreferences chartPreferenceNode = InstanceScope.INSTANCE.getNode( "org.simantics.charts" ); String s = chartPreferenceNode.get("chart.valueformat", ValueFormat.Default.name()); ValueFormat valueFormat = ValueFormat.valueOf( s ); return resolveLabel(graph, item, valueFormat, synchronous); } public static String resolveLabel(ReadGraph graph, Resource item, ValueFormat valueFormat, boolean synchronous) throws DatabaseException { return resolveLabel(graph, item, valueFormat, synchronous, true, true); } public static String resolveLabel(ReadGraph graph, Resource item, ValueFormat valueFormat, boolean synchronous, boolean tryLabel, boolean showValue) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); ModelingResources MOD = ModelingResources.getInstance(graph); String label = tryLabel ? graph.getPossibleRelatedValue(item, L0.HasLabel, Bindings.STRING) : null; boolean labelDefined = isNonempty(label); if (!showValue && labelDefined) return label; // Create label from rvi Binding rviBinding = graph.getService(Databoard.class).getBindingUnchecked( RVI.class ); RVI rvi = graph.getPossibleRelatedValue(item, MOD.Subscription_Item_VariableId, rviBinding); if (rvi == null) return NO_VARIABLE_ID; Resource model = graph.syncRequest(new PossibleIndexRoot(item)); if (model != null) { ModelContexts contexts = graph.syncRequest(new ModelContextsRequest(model), TransientCacheAsyncListener.instance()); Variable configurationContext = contexts.getConfigurationContext(); Variable experimentContext = contexts.getExperimentContext(); if (configurationContext != null) { // Resolve variable and take note of the resolution context Variable variable = null; Variable resolutionContext = experimentContext; String resolutionContextURI = contexts.getExperimentContextURI(); if (showValue && experimentContext != null) variable = rvi.resolvePossible(graph, experimentContext); if (variable == null) { resolutionContext = configurationContext; resolutionContextURI = contexts.getConfigurationContextURI(); variable = rvi.resolvePossible(graph, configurationContext); } if (variable != null) { if (!labelDefined) { label = relativeURI(graph, variable, resolutionContextURI); if (label == null) label = rvi.toPossibleString(graph, configurationContext); if (label != null) { label = removeVariablePrefixPath(label); label = URIStringUtils.unescape(label); } } if (showValue && resolutionContext == experimentContext) { StringBuilder sb = new StringBuilder(label); Double gain = graph.getPossibleRelatedValue(item, MOD.Subscription_Item_Gain, Bindings.DOUBLE); Double bias = graph.getPossibleRelatedValue(item, MOD.Subscription_Item_Bias, Bindings.DOUBLE); String unit = graph.getPossibleRelatedValue(item, MOD.Subscription_Item_Unit, Bindings.STRING); boolean oldSync = graph.setSynchronous(synchronous); try { Object value = graph.syncRequest( new PossibleVariableValue(variable) ); sb = formatValue(value, gain, bias, unit, valueFormat, sb); } catch (PendingVariableException e) { sb.append(" ()"); } finally { graph.setSynchronous(oldSync); } label = sb.toString(); } } } } return label != null ? label : NO_VARIABLE_ID; } private static StringBuilder formatValue(Object value, Double gain, Double bias, String unit, ValueFormat valueFormat, StringBuilder sb) { if (value instanceof Number) { double d = ((Number) value).doubleValue(); double ad = d; if (gain != null) ad *= gain; if (bias != null) ad += bias; sb.append(" (").append(valueFormat.format.format(ad)); } else { sb.append(" (").append(FormattingUtils.engineeringFormat(value)); } if (unit != null && !unit.isEmpty()) { sb.append(' ').append(unit); } return sb.append(')'); } public static String removeVariablePrefixPath(String rvi) { // Apros-specific logics: // 1. remove path prefix // 2. change IndexReferences (i-N) into "(N+1)" Apros-style indexing int propIndex = rvi.indexOf('#'); if (propIndex == -1) return rvi; int prevSlash = rvi.lastIndexOf('/', propIndex); if (prevSlash == -1) return rvi; Pair attrKey = attributeKey(rvi, propIndex + 1); return rvi.substring(prevSlash + 1, propIndex + 1) + attrKey.first + (attrKey.second != null ? "(" + (attrKey.second + 1) + ")" : ""); } private static Pair attributeKey(String key, int start) { int iy = key.lastIndexOf('/'); boolean isIndexed = iy >= start; if (isIndexed) { ChildReference child = ChildReference.parsePath(key.substring(iy + 1)); if (child instanceof IndexReference) return Pair.make(key.substring(start, iy), ((IndexReference) child).getIndex()); } return Pair.make(key.substring(start), null); } private static boolean isNonempty(String label) { return label != null && !label.trim().isEmpty(); } private static String relativeURI(ReadGraph graph, Variable variable, String contextURI) throws DatabaseException { return relativeURI(variable.getURI(graph), contextURI); } private static String relativeURI(String fullURI, String contextURI) { return fullURI.substring(contextURI.length()); } }