/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.browsing.ui.graph.impl; import java.util.Map; import org.simantics.Simantics; import org.simantics.browsing.ui.BuiltinKeys; import org.simantics.browsing.ui.BuiltinKeys.LabelerKey; import org.simantics.browsing.ui.GraphExplorer.ModificationContext; import org.simantics.browsing.ui.NodeContext; import org.simantics.browsing.ui.PrimitiveQueryUpdater; import org.simantics.browsing.ui.common.ColumnKeys; import org.simantics.browsing.ui.common.modifiers.EnumerationValue; import org.simantics.browsing.ui.common.property.IArrayProperty; import org.simantics.browsing.ui.common.property.IProperty; import org.simantics.browsing.ui.content.Labeler; import org.simantics.browsing.ui.content.LabelerFactory; import org.simantics.databoard.Bindings; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.type.Component; 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.common.primitiverequest.PossibleRelatedValue2; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.adapter.StringIndexModifier; import org.simantics.db.layer0.adapter.StringModifier; import org.simantics.db.layer0.adapter.TObjectIntPair; import org.simantics.db.management.ISessionContext; import org.simantics.layer0.Layer0; import org.simantics.utils.datastructures.ArrayMap; import org.simantics.utils.datastructures.slice.ValueRange; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Tuukka Lehtonen */ public class ArrayPropertyLabelerFactory implements LabelerFactory { @Override public Labeler create(PrimitiveQueryUpdater manager, NodeContext context, LabelerKey key) { Object o = context.getConstant(BuiltinKeys.INPUT); //System.out.println("ArrayPropertyLabelerFactory: " + o); if (o instanceof IArrayProperty) { return new ArrayPropertyLabeler(manager, context, key); } else if (o instanceof IProperty) { return new PropertyLabeler(manager, context, key); } return null; } static class PropertyLabeler extends LazyGraphLabeler { NodeContext context; public PropertyLabeler(PrimitiveQueryUpdater updater, NodeContext context, LabelerKey key) { super(updater, context, key); this.context = context; } @Override public Map labels(ReadGraph graph) throws DatabaseException { IProperty prop = (IProperty) context.getConstant(BuiltinKeys.INPUT); Resource[] r = prop.adapt(Resource[].class); if (r == null) return new ArrayMap(ColumnKeys.KEYS_PROPERTY_VALUE, new String[] { prop.toString(), "N/A" }); // System.out.println(prop + " [" + prop.getData(Resource[].class).length + "]"); // for (Resource rr : prop.getData(Resource[].class)) // System.out.println(" " + prop + " " + NameUtils.getSafeName(graph, rr)); String property = ""; String value = ""; if (r.length == 3) { property = LabelerUtil.safeStringRepresentation(graph, r[1]); value = graph.getPossibleRelatedAdapter(r[0], r[1], String.class); if (value == null) value = LabelerUtil.safeStringRepresentation(graph, r[2]); } //System.out.println("LABEL: " + property + " - " + value); return new ArrayMap(ColumnKeys.KEYS_PROPERTY_VALUE, new String[] { property, value }); } @Override public Modifier getModifier(ModificationContext modificationContext, String key) { final ISessionContext session = Simantics.getSessionContext(); if (session == null) return null; final IProperty prop = (IProperty) context.getConstant(BuiltinKeys.INPUT); final Resource[] data = prop.adapt(Resource[].class); if (data == null) return null; if (data.length != 3) return null; if (ColumnKeys.VALUE.equals(key)) { try { // Make sure that the property is not read-only before editing Layer0 L0 = Layer0.getInstance(session.getSession()); Boolean readOnly = session.getSession().syncRequest(new PossibleRelatedValue2(data[1], L0.readOnly, Bindings.BOOLEAN)); if (Boolean.TRUE.equals(readOnly)) return null; EnumerationValue enu = session.getSession().syncRequest(new GetEnumerationValue(data[2])); if (enu != null) { return new GraphEnumerationModifier(session.getSession(), data[0], data[1], enu.getEnumeration(), enu.getEnumeratedValue()); } else { final Resource subject = data[0], predicate = data[1], object = data[2]; return new GraphFactoryStringModifier(subject, predicate, object, session.getSession()) { @Override public void doModify(WriteGraph graph, String label) throws DatabaseException { if (IProperty.ASSERTED.contains(prop.getType())) { // 1. Instantiate new property based on default value and attach it to the module. Layer0 L0 = Layer0.getInstance(graph); Resource newValue = graph.newResource(); for (Resource type : graph.getObjects(object, L0.InstanceOf)) graph.claim(newValue, L0.InstanceOf, null, type); if(!graph.hasStatement(newValue, L0.HasDataType)) { Binding b = Bindings.getBindingUnchecked(Datatype.class); Datatype dt = graph.getRelatedValue(object, L0.HasDataType, b); graph.addLiteral(newValue, L0.HasDataType, L0.HasDataType_Inverse, L0.DataType, dt, b); } graph.claim(subject, predicate, newValue); // 2. Adapt StringModifier for the new property StringModifier sm = graph.adapt(newValue, StringModifier.class); // 3. Modify the new property with the specified label sm.modify(graph, label); } else { getModifier().modify(graph, label); } } }; } } catch (DatabaseException e) { throw new RuntimeException(e); } } return null; } @Override public Logger getLogger() { return LoggerFactory.getLogger(PropertyLabeler.class); } } static class ArrayPropertyLabeler extends LazyGraphLabeler { NodeContext context; public ArrayPropertyLabeler(PrimitiveQueryUpdater updater, NodeContext context, LabelerKey key) { super(updater, context, key); this.context = context; } @Override public Map labels(ReadGraph graph) throws DatabaseException { IArrayProperty prop = (IArrayProperty) context.getConstant(BuiltinKeys.INPUT); ValueRange range = prop.getRange(); Resource[] r = prop.adapt(Resource[].class); if (r == null) return new ArrayMap(ColumnKeys.KEYS_PROPERTY_VALUE, new String[] { prop.toString(), "N/A" }); String property = ""; String value = ""; if (!prop.isSlice()) { property = LabelerUtil.safeStringRepresentation(graph, r[1]); String valueType = GraphPropertyUtil.tryGetValueTypeString(graph, r[2], range.size()); value = valueType; } else if (range.isSingle()) { Layer0 L0 = Layer0.getInstance(graph); property = range.toString(); value = LabelerUtil.safeStringRepresentation(graph, r[2], range.start()); Datatype dt = graph.getPossibleRelatedValue(r[2], L0.HasDataType, Bindings.getBindingUnchecked(Datatype.class)); if(dt != null) { if(dt instanceof RecordType) { RecordType rt = (RecordType)dt; if(range.start() < rt.getComponentCount()) { Component comp = rt.getComponent(range.start()); property = comp.name; } } } } else { property = range.toString(); } return new ArrayMap(ColumnKeys.KEYS_PROPERTY_VALUE, new String[] { property, value }); } @Override public Modifier getModifier(ModificationContext modificationContext, String key) { ISessionContext session = Simantics.getSessionContext(); if (session == null) return null; // Only single values can be edited. final IArrayProperty prop = (IArrayProperty) context.getConstant(BuiltinKeys.INPUT); if (!prop.getRange().isSingle()) return null; final Resource[] data = prop.getData(Resource[].class); if (data == null) return null; if (data.length != 3) return null; if (ColumnKeys.VALUE.equals(key)) { // TODO: fix boolean array editing case to work with a combo box. try { Layer0 L0 = Layer0.getInstance(session.getSession()); Boolean readOnly = session.getSession().syncRequest(new PossibleRelatedValue2(data[1], L0.readOnly, Bindings.BOOLEAN)); if (Boolean.TRUE.equals(readOnly)) return null; return new GraphStringIndexModifier(context, session.getSession(), prop.getRange().start()) { // StringRepresentation representation; @Override protected void initializeGraphModifier(ReadGraph g) { // representation = g.adapt(getResourceToModify(), g.getBuiltins().HasStringRepresentationInterface); } @Override public TObjectIntPair createModifierInput(String fromLabel) { return new TObjectIntPair(fromLabel, prop.getRange().start()); } @Override public void doModify(WriteGraph graph, TObjectIntPair label) throws DatabaseException { //System.out.println("Performing modification for " + representation.get(graph)); if (IProperty.ASSERTED.contains(prop.getType())) { // 1. Instantiate new property based on default value and attach it to the module. Layer0 L0 = Layer0.getInstance(graph); Resource module = data[0], attribute = data[1], defaultValue = data[2]; Resource newValue = graph.newResource(); for (Resource type : graph.getObjects(defaultValue, L0.InstanceOf)) graph.claim(newValue, L0.InstanceOf, null, type); graph.claim(module, attribute, newValue); Object defaultValueValue = graph.getValue(defaultValue); //if(defaultValueValue instanceof float[]) System.out.println("new property : " + Arrays.toString((float[])defaultValueValue)); graph.claimValue(newValue, defaultValueValue); // 2. Adapt StringIndexModifier for the new property StringIndexModifier sm = graph.adapt(newValue, StringIndexModifier.class); // 3. Modify the new property with the specified label sm.modify(graph, label); } else { getModifier().modify(graph, label); } } }; } catch (DatabaseException e) { e.printStackTrace(); return null; } } return null; } @Override public Logger getLogger() { return LoggerFactory.getLogger(ArrayPropertyLabeler.class); } }; }