From: Jussi Koskela Date: Wed, 2 Sep 2020 09:17:31 +0000 (+0300) Subject: Fixed multiple issues causing dangling references to discarded queries X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=commitdiff_plain;h=HEAD;hp=195c63dd5c7600170f594750de96793ebf06a0ad Fixed multiple issues causing dangling references to discarded queries gitlab #594 Change-Id: Iaa6b12f60d7dfa2bbcbc9614ef837973885586cc --- diff --git a/bundles/org.simantics.charts/src/org/simantics/charts/query/ChartAndSubscriptionItemData.java b/bundles/org.simantics.charts/src/org/simantics/charts/query/ChartAndSubscriptionItemData.java index 9438e404b..8f2bd26f8 100644 --- a/bundles/org.simantics.charts/src/org/simantics/charts/query/ChartAndSubscriptionItemData.java +++ b/bundles/org.simantics.charts/src/org/simantics/charts/query/ChartAndSubscriptionItemData.java @@ -48,7 +48,7 @@ public class ChartAndSubscriptionItemData extends Bean { // Output @Optional public String subscription = "Default"; - @Optional public String unit = ""; + @Optional public String unit; @Optional public Double min, max, deadband, interval, gain, bias; @Optional public DrawMode drawmode; @Optional public Scale scale; diff --git a/bundles/org.simantics.db.common/META-INF/MANIFEST.MF b/bundles/org.simantics.db.common/META-INF/MANIFEST.MF index 63b3e6bfc..a29371495 100644 --- a/bundles/org.simantics.db.common/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.db.common/META-INF/MANIFEST.MF @@ -7,7 +7,6 @@ Bundle-Vendor: VTT Technical Research Centre of Finland Bundle-RequiredExecutionEnvironment: JavaSE-11 Require-Bundle: org.simantics.db;bundle-version="1.1.0";visibility:=reexport, gnu.trove3;bundle-version="3.0.3", - org.apache.log4j;bundle-version="1.2.15", org.simantics.layer0;bundle-version="1.0.0";visibility:=reexport, org.simantics.graph;bundle-version="1.1.4", org.simantics.scl.reflection;bundle-version="1.0.0";visibility:=reexport, diff --git a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/ErrorLogger.java b/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/ErrorLogger.java deleted file mode 100644 index 68ad37438..000000000 --- a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/ErrorLogger.java +++ /dev/null @@ -1,115 +0,0 @@ -/******************************************************************************* - * 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.db.common.utils; - -import java.util.Properties; - -import org.apache.log4j.Logger; - -/* - * - * @deprecated in favor of org.simantics.db.common.Logger. Will be removed in Simantics 1.2 - * - */ -@Deprecated -public class ErrorLogger { - public static final boolean ECHO = false; - public static final Properties defaultProperties = new Properties(); - static { - defaultProperties.put("log4j.rootCategory", "ERROR, default"); - defaultProperties.put("log4j.appender.default", "org.apache.log4j.FileAppender"); - defaultProperties.put("log4j.appender.default.File", "db-client-deprecated.log"); - defaultProperties.put("log4j.appender.default.append", "false"); - defaultProperties.put("log4j.appender.default.layout", "org.apache.log4j.PatternLayout"); - defaultProperties.put("log4j.appender.default.layout.ConversionPattern", "%-6r [%15.15t] %-5p %30.30c - %m%n"); - } - private static LogManager defaultLogManager = new LogManager(defaultProperties); - private static final ErrorLogger defaultErrorLogger = new ErrorLogger(LogManager.class); - private Logger logger; - ErrorLogger(Class clazz) { - logger = defaultLogManager.getLogger(clazz); - } - - /** - * Log a trace event. - * - * @param message message of the trace - * @param exception the exception, or null - */ - public void logTrace(String message, Throwable exception) { - // Errors are much more useful with a stack trace! - if (exception == null) { - exception = new RuntimeException(); - } - logger.trace(message, exception); - } - - /** - * Log an info event. - * - * @param message message of the info - * @param exception the exception, or null - */ - public void logInfo(String message, Throwable exception) { - // Errors are much more useful with a stack trace! - if (exception == null) { - exception = new RuntimeException(); - } - logger.info(message, exception); - } - - /** - * Log an error event. - * - * @param message message of the error - * @param exception the exception, or null - */ - public void logError(String message, Throwable exception) { - // Errors are much more useful with a stack trace! - if (exception == null) { - exception = new RuntimeException(); - } - logger.error(message, exception); - } - - public static ErrorLogger getDefault() { - return defaultErrorLogger; - } - - public static LogManager getDefaultLogManager() { - return defaultLogManager; - } - public static void defaultLogError(Throwable exception) { - getDefault().logError(exception.getLocalizedMessage(), exception); - if(ECHO) exception.printStackTrace(); - } - public static void defaultLogError(String message) { - getDefault().logError(message, null); - if(ECHO) - System.err.println(message); - } - public static void defaultLogError(String message, Throwable exception) { - getDefault().logError(message, exception); - if(ECHO) - System.err.println(message); - } - public static void defaultLogInfo(String message) { - getDefault().logInfo(message, null); - if(ECHO) - System.err.println(message); - } - public static void defaultLogTrace(String message) { - getDefault().logTrace(message, null); - if(ECHO) - System.err.println(message); - } -} diff --git a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/LogManager.java b/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/LogManager.java deleted file mode 100644 index 9abae439d..000000000 --- a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/LogManager.java +++ /dev/null @@ -1,151 +0,0 @@ -/******************************************************************************* - * 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.db.common.utils; - -import java.util.Properties; - -import org.apache.log4j.Hierarchy; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; -import org.apache.log4j.spi.LoggerFactory; -import org.apache.log4j.spi.RootLogger; - -/** - * This class encapsulates a Log4J Hierarchy and centralizes all Logger access. - */ -public class LogManager { - - private Hierarchy hierarchy; - - /** - * Creates a new LogManager. Saves the log and state location. - * Creates a new Hierarchy and add a new EventListener to it. - * Configure the hierarchy with the properties passed. Add this object to - * the list of active log managers. - * - * @param properties log configuration properties - */ - public LogManager(Properties properties) { - this.hierarchy = new Hierarchy(new RootLogger(Level.DEBUG)); - new PropertyConfigurator().doConfigure(properties, this.hierarchy); - } - - /** - * Checks if this PluginLogManager is disabled for this level. - * - * @param level level value - * @return boolean true if it is disabled - */ - public boolean isDisabled(int level) { - return this.hierarchy.isDisabled(level); - } - - /** - * Enable logging for logging requests with level l or higher. By default - * all levels are enabled. - * - * @param level level object - */ - public void setThreshold(Level level) { - this.hierarchy.setThreshold(level); - } - - /** - * The string version of setThreshold(Level level) - * - * @param level level string - */ - public void setThreshold(String level) { - this.hierarchy.setThreshold(level); - } - - /** - * Get the repository-wide threshold. - * - * @return Level - */ - public Level getThreshold() { - return this.hierarchy.getThreshold(); - } - - /** - * Returns a new logger instance named as the first parameter using the - * default factory. If a logger of that name already exists, then it will be - * returned. Otherwise, a new logger will be instantiated and then linked - * with its existing ancestors as well as children. - * - * @param clazz the class to get the logger for - * @return Logger - */ - public Logger getLogger(Class clazz) { - return this.hierarchy.getLogger(clazz.getName()); - } - - /** - * Returns a new logger instance named as the first parameter using the - * default factory. If a logger of that name already exists, then it will be - * returned. Otherwise, a new logger will be instantiated and then linked - * with its existing ancestors as well as children. - * - * @param name logger name - * @return Logger - */ - public Logger getLogger(String name) { - return this.hierarchy.getLogger(name); - } - - /** - * The same as getLogger(String name) but using a factory instance instead - * of a default factory. - * - * @param name logger name - * @param factory factory instance - * @return Logger - */ - public Logger getLogger(String name, LoggerFactory factory) { - return this.hierarchy.getLogger(name, factory); - } - - /** - * Returns the root of this hierarchy. - * - * @return Logger - */ - public Logger getRootLogger() { - return this.hierarchy.getRootLogger(); - } - - /** - * Checks if this logger exists. - * - * @return Logger - */ - public Logger exists(String name) { - return this.hierarchy.exists(name); - } - - /** - * Disposes the logger hierarchy - */ - public void shutdown() { - this.hierarchy.shutdown(); - } - - /** - * Resets configuration values to its defaults. - */ - public void resetConfiguration() { - this.hierarchy.resetConfiguration(); - } - -} \ No newline at end of file diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ArraySet.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ArraySet.java deleted file mode 100644 index 1360cef74..000000000 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ArraySet.java +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************* - * 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.db.impl.graph; - -import java.util.Collection; -import java.util.Iterator; -import java.util.Set; - -import org.simantics.db.Resource; -import org.simantics.db.impl.query.IntSet; -import org.simantics.db.impl.query.QuerySupport; - -public class ArraySet implements Set { - - final Resource[] set; - - ArraySet(IntSet intSet, QuerySupport support) { - - if(intSet.data == null) { - if(intSet.sizeOrData != IntSet.NO_DATA) { - set = new Resource[] { support.getResource(intSet.sizeOrData) }; - } else { - set = Resource.NONE; - } - } else { - set = new Resource[intSet.sizeOrData]; - for(int i=0;i c) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean contains(Object o) { - for(int i=0;i c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isEmpty() { - return set.length == 0; - } - - @Override - public Iterator iterator() { - - class ArraySetIterator implements Iterator { - - int next = 0; - - @Override - public boolean hasNext() { - return next < set.length; - } - - @Override - public Resource next() { - return set[next++]; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - } - - return new ArraySetIterator(); - - } - - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removeAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean retainAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public int size() { - return set.length; - } - - @Override - public Object[] toArray() { - throw new UnsupportedOperationException(); - } - - @Override - public T[] toArray(T[] a) { - throw new UnsupportedOperationException(); - } - -} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AssertedPredicates.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AssertedPredicates.java index b4104e965..23fbe95ec 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AssertedPredicates.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AssertedPredicates.java @@ -241,5 +241,11 @@ final public class AssertedPredicates extends UnaryQuery { }); } - + + @Override + public void serializeValue(QuerySerializer serializer) { + IntArray is = getResult(); + is.serialize(serializer); + } + } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AssertedPredicatesFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AssertedPredicatesFactory.java new file mode 100644 index 000000000..c76bc51ee --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AssertedPredicatesFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class AssertedPredicatesFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + AssertedPredicates result = reference(deserializer); + IntArray ia = IntArray.deserialize(deserializer); + result.setResult(ia); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readAssertedPredicates(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AssertedStatementsFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AssertedStatementsFactory.java new file mode 100644 index 000000000..708ce6686 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AssertedStatementsFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class AssertedStatementsFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + AssertedStatements result = reference(deserializer); + IntArray ia = IntArray.deserialize(deserializer); + result.setResult(ia); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readAssertedStatements(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AsyncMultiReadEntry.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AsyncMultiReadEntry.java index ea88d1791..788044807 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AsyncMultiReadEntry.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AsyncMultiReadEntry.java @@ -190,4 +190,9 @@ final public class AsyncMultiReadEntry extends CacheEntryBase extends CacheEntryBase> i } } + @Override + public String classId() { + return null; + } + } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/BinaryQuery.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/BinaryQuery.java index d699ea825..04df0d00c 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/BinaryQuery.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/BinaryQuery.java @@ -66,4 +66,15 @@ public abstract class BinaryQuery extends CacheEntryBase i abstract public void removeEntry(QueryProcessor provider); + @Override + public long cluster(QueryProcessor processor) { + return processor.cluster(r1()); + } + + @Override + public void serializeKey(QuerySerializer serializer) { + serializer.addResource(r1()); + serializer.addResource(r2()); + } + } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntry.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntry.java index 1cdcbde9d..a650f32ce 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntry.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntry.java @@ -11,6 +11,8 @@ *******************************************************************************/ package org.simantics.db.impl.query; +import java.util.Collection; + import org.simantics.db.exception.DatabaseException; import org.simantics.db.impl.graph.ReadGraphImpl; @@ -40,10 +42,11 @@ public abstract class CacheEntry { abstract Query getQuery(); abstract CacheEntry pruneFirstParents(); + abstract void pruneParentSet(); abstract void removeParent(CacheEntry entry); abstract void addParent(CacheEntry entry); abstract boolean hasParents(); - abstract Iterable> getParents(QueryProcessor processor); + abstract Collection> getParents(QueryProcessor processor); abstract CacheEntry getFirstParent(QueryProcessor processor); abstract boolean moreThanOneParent(QueryProcessor processor); abstract int parentCount(QueryProcessor processor); diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntryBase.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntryBase.java index e79f99dea..98e7f0d00 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntryBase.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CacheEntryBase.java @@ -12,6 +12,7 @@ package org.simantics.db.impl.query; import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import org.simantics.databoard.Bindings; @@ -277,7 +278,31 @@ public abstract class CacheEntryBase extends CacheEntry { } } - + + @Override + void pruneParentSet() { + // First parent is discarded => look for more parents + if(p2OrParents instanceof QueryIdentityHashSet) { + + QueryIdentityHashSet set = (QueryIdentityHashSet)p2OrParents; + set.removeDiscardedReally(); + if(set.isEmpty()) p2OrParents = null; + + } else if(p2OrParents instanceof CacheEntry) { + + CacheEntry entry = (CacheEntry)p2OrParents; + if(entry.isDiscarded()) { + // Second entry is also discarded => all empty + p2OrParents = null; + } + + } else { + + // Nothing left + + } + } + @Override final public void removeParent(CacheEntry entry) { @@ -339,7 +364,7 @@ public abstract class CacheEntryBase extends CacheEntry { } @Override - final public Iterable> getParents(QueryProcessor processor) { + final public Collection> getParents(QueryProcessor processor) { ArrayList> result = new ArrayList>(); if(p1 != null) result.add(p1); @@ -471,5 +496,44 @@ public abstract class CacheEntryBase extends CacheEntry { public CacheEntryBase() { } + + public String classId() { + return getClass().getName(); + } + + public void serializeKey(QuerySerializer serializer) { + throw new IllegalStateException("Cannot serialize query key for " + this); + } + + public void serializeValue(QuerySerializer serializer) { + throw new IllegalStateException("Cannot serialize query value for " + this); + } + + public void serializeParents(QuerySerializer serializer) { + Collection> ps = getParents(serializer.getQueryProcessor()); + int sizePos = serializer.writeUnknownSize(); + int actual = 0; + for(CacheEntry entry : ps) { + CacheEntryBase b = (CacheEntryBase)entry; + String cid = b.classId(); + if(cid == null) + continue; + serializer.serializeId(b.classId()); + b.serializeKey(serializer); + actual++; + } + serializer.setUnknownSize(sizePos, actual); + } + + public long cluster(QueryProcessor processor) { + throw new IllegalStateException("Cannot compute query cluster for " + this); + } + + public void serialize(QuerySerializer serializer) { + serializer.serializeId(classId()); + serializeKey(serializer); + serializeValue(serializer); + serializeParents(serializer); + } } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ChildMap.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ChildMap.java index 8effbb1d5..79d3106a8 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ChildMap.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ChildMap.java @@ -142,6 +142,16 @@ public final class ChildMap extends UnaryQueryP> { } + @Override + public void serializeValue(QuerySerializer serializer) { + ObjectResourceIdMap is = getResult(); + serializer.writeLE(is.size()); + for(String s : is.keySet()) { + serializer.addString(s); + serializer.addResource(is.getId(s)); + } + } + @Override public String toString() { return "ChildMap[" + id + "]"; diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ChildMapFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ChildMapFactory.java new file mode 100644 index 000000000..bf179b523 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ChildMapFactory.java @@ -0,0 +1,28 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.ObjectResourceIdMap; +import org.simantics.db.exception.DatabaseException; + +public class ChildMapFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + ChildMap result = reference(deserializer); + ObjectResourceIdMap map = deserializer.createChildMap(); + int size = deserializer.readLE4(); + for(int i=0;i T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readChildMap(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CollectionBinaryQuery.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CollectionBinaryQuery.java index cd139655c..6e1692ba4 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CollectionBinaryQuery.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CollectionBinaryQuery.java @@ -11,9 +11,6 @@ *******************************************************************************/ package org.simantics.db.impl.query; - - - abstract public class CollectionBinaryQuery extends BinaryQuery { public CollectionBinaryQuery(final int r1, final int r2) { @@ -33,5 +30,11 @@ abstract public class CollectionBinaryQuery extends BinaryQuery { if(size == 0) setResult(IntArray.EMPTY); else v.trim(); } - + + @Override + public void serializeValue(QuerySerializer serializer) { + IntArray is = getResult(); + is.serialize(serializer); + } + } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CollectionUnaryQuery.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CollectionUnaryQuery.java index 90bb03554..2eaeca472 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CollectionUnaryQuery.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CollectionUnaryQuery.java @@ -96,4 +96,10 @@ public abstract class CollectionUnaryQuery extends UnaryQuery impl except(throwable); } + @Override + public void serializeValue(QuerySerializer serializer) { + IntArray is = getResult(); + is.serialize(serializer); + } + } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/DirectObjectsFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/DirectObjectsFactory.java new file mode 100644 index 000000000..323ec2134 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/DirectObjectsFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class DirectObjectsFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + DirectObjects result = reference(deserializer); + IntArray ia = IntArray.deserialize(deserializer); + result.setResult(ia); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readDirectObjects(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/DirectPredicates.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/DirectPredicates.java index 1a006369a..ee0faa1cf 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/DirectPredicates.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/DirectPredicates.java @@ -16,7 +16,7 @@ import org.simantics.db.exception.DatabaseException; import org.simantics.db.impl.graph.ReadGraphImpl; import org.simantics.db.impl.procedure.InternalProcedure; -public final class DirectPredicates extends UnaryQueryP { +public final class DirectPredicates extends UnaryQueryPIntSet { DirectPredicates(final int resource) { super(resource); diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/DirectPredicatesFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/DirectPredicatesFactory.java new file mode 100644 index 000000000..e707e62e7 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/DirectPredicatesFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class DirectPredicatesFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + DirectPredicates result = reference(deserializer); + IntSet is = IntSet.deserialize(deserializer); + result.setResult(is); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readDirectPredicates(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ExternalReadEntry.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ExternalReadEntry.java index d04404339..2980b9b15 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ExternalReadEntry.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ExternalReadEntry.java @@ -28,7 +28,7 @@ final public class ExternalReadEntry extends CacheEntryBase final LinkedList items = new LinkedList(); protected ExternalRead id; - protected ReadGraphImpl graph; + protected QueryProcessor processor; protected boolean registered = false; @Override @@ -49,7 +49,7 @@ final public class ExternalReadEntry extends CacheEntryBase public void discard() { id.unregistered(); id = null; - graph = null; + processor = null; super.discard(); } @@ -65,7 +65,7 @@ final public class ExternalReadEntry extends CacheEntryBase public ExternalReadEntry(ExternalRead request, ReadGraphImpl graph) { assert request != null; this.id = request; - this.graph = graph; + this.processor = graph.processor; } @Override @@ -213,7 +213,7 @@ final public class ExternalReadEntry extends CacheEntryBase synchronized(items) { items.addLast(result); - graph.processor.updatePrimitive(id); + processor.updatePrimitive(id); // TODO: implement flags/logic in ExternalRead to state that all but the latest request result can be evaporated // In some cases where data is produced really fast this might be necessary but currently this queueing will do. } @@ -229,7 +229,12 @@ final public class ExternalReadEntry extends CacheEntryBase @Override public boolean isDisposed() { - return registered && (isDiscarded() || !graph.processor.isBound(this)); + return registered && (isDiscarded() || !processor.isBound(this)); } - + + @Override + public String classId() { + return null; + } + } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/IntArray.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/IntArray.java index 6ee30ad70..53b447f08 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/IntArray.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/IntArray.java @@ -13,6 +13,8 @@ package org.simantics.db.impl.query; import java.util.Arrays; +import org.simantics.db.exception.DatabaseException; + final public class IntArray { @@ -111,7 +113,27 @@ final public class IntArray { } return result; } - + + public void serialize(QuerySerializer serializer) { + int size = size(); + serializer.writeLE(size); + if(size == 1) { + serializer.addResource(sizeOrData); + } else { + for(int i=0;i implement except(throwable); } + @Override + public void serializeValue(QuerySerializer serializer) { + IntArray is = getResult(); + is.serialize(serializer); + } + } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ObjectsFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ObjectsFactory.java new file mode 100644 index 000000000..f6758e618 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ObjectsFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class ObjectsFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + Objects result = reference(deserializer); + IntArray ia = IntArray.deserialize(deserializer); + result.setResult(ia); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readObjects(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/OrderedSetFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/OrderedSetFactory.java new file mode 100644 index 000000000..9b5f581ba --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/OrderedSetFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class OrderedSetFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + OrderedSet result = reference(deserializer); + IntArray ia = IntArray.deserialize(deserializer); + result.setResult(ia); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readOrderedSet(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Predicates.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Predicates.java index 9445db03b..982d8019c 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Predicates.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Predicates.java @@ -19,7 +19,7 @@ import org.simantics.db.request.RequestFlags; import gnu.trove.procedure.TIntProcedure; -final public class Predicates extends UnaryQueryP { +final public class Predicates extends UnaryQueryPIntSet { Predicates(final int r) { super(r); diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/PredicatesFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/PredicatesFactory.java new file mode 100644 index 000000000..c86e43ce6 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/PredicatesFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class PredicatesFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + Predicates result = reference(deserializer); + IntSet ia = IntSet.deserialize(deserializer); + result.setResult(ia); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readPredicates(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/PrincipalTypesFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/PrincipalTypesFactory.java new file mode 100644 index 000000000..ccd4ddc47 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/PrincipalTypesFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class PrincipalTypesFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + PrincipalTypes result = reference(deserializer); + IntArray ia = IntArray.deserialize(deserializer); + result.setResult(ia); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readPrincipalTypes(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCacheBase.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCacheBase.java index f80fb5098..b0bca1350 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCacheBase.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCacheBase.java @@ -4,13 +4,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.Semaphore; -import org.simantics.databoard.Bindings; import org.simantics.db.AsyncReadGraph; -import org.simantics.db.DevelopmentKeys; import org.simantics.db.ObjectResourceIdMap; import org.simantics.db.ReadGraph; import org.simantics.db.RelationInfo; -import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; import org.simantics.db.impl.graph.ReadGraphImpl; import org.simantics.db.impl.procedure.InternalProcedure; @@ -24,7 +21,6 @@ import org.simantics.db.request.AsyncRead; import org.simantics.db.request.ExternalRead; import org.simantics.db.request.MultiRead; import org.simantics.db.request.Read; -import org.simantics.utils.Development; import gnu.trove.map.hash.THashMap; import gnu.trove.map.hash.TObjectIntHashMap; @@ -980,5 +976,158 @@ public class QueryCacheBase { static boolean shouldCache(QueryProcessor processor, Object o) { return false; } + + AssertedPredicates getOrCreateAssertedPredicates(int r) { + AssertedPredicates entry = (AssertedPredicates)assertedPredicatesMap.get(r); + if(entry == null) { + entry = new AssertedPredicates(r); + assertedPredicatesMap.put(keyR(r), entry); + } + return entry; + } + AssertedStatements getOrCreateAssertedStatements(int r1, int r2) { + AssertedStatements entry = (AssertedStatements)assertedStatementsMap.get(r1, r2); + if(entry == null) { + entry = new AssertedStatements(r1, r2); + assertedStatementsMap.put(keyR2(r1, r2), entry); + } + return entry; + } + + ChildMap getOrCreateChildMap(int r) { + ChildMap entry = (ChildMap)childMapMap.get(r); + if(entry == null) { + entry = new ChildMap(r); + childMapMap.put(keyR(r), entry); + } + return entry; + } + + DirectObjects getOrCreateDirectObjects(int r1, int r2) { + DirectObjects entry = (DirectObjects)directObjectsMap.get(r1, r2); + if(entry == null) { + entry = new DirectObjects(r1, r2); + directObjectsMap.put(keyR2(r1, r2), entry); + } + return entry; + } + + DirectPredicates getOrCreateDirectPredicates(int r) { + DirectPredicates entry = (DirectPredicates)directPredicatesMap.get(r); + if(entry == null) { + entry = new DirectPredicates(r); + directPredicatesMap.put(keyR(r), entry); + } + return entry; + } + + Objects getOrCreateObjects(int r1, int r2) { + Objects entry = (Objects)objectsMap.get(r1, r2); + if(entry == null) { + entry = new Objects(r1, r2); + objectsMap.put(keyR2(r1, r2), entry); + } + return entry; + } + + OrderedSet getOrCreateOrderedSet(int r) { + OrderedSet entry = (OrderedSet)orderedSetMap.get(r); + if(entry == null) { + entry = new OrderedSet(r); + orderedSetMap.put(keyR(r), entry); + } + return entry; + } + + Predicates getOrCreatePredicates(int r) { + Predicates entry = (Predicates)predicatesMap.get(r); + if(entry == null) { + entry = new Predicates(r); + predicatesMap.put(keyR(r), entry); + } + return entry; + } + + PrincipalTypes getOrCreatePrincipalTypes(int r) { + PrincipalTypes entry = (PrincipalTypes)principalTypesMap.get(r); + if(entry == null) { + entry = new PrincipalTypes(r); + principalTypesMap.put(keyR(r), entry); + } + return entry; + } + + RelationInfoQuery getOrCreateRelationInfoQuery(int r) { + RelationInfoQuery entry = (RelationInfoQuery)relationInfoQueryMap.get(r); + if(entry == null) { + entry = new RelationInfoQuery(r); + relationInfoQueryMap.put(keyR(r), entry); + } + return entry; + } + + Statements getOrCreateStatements(int r1, int r2) { + Statements entry = (Statements)statementsMap.get(r1, r2); + if(entry == null) { + entry = new Statements(r1, r2); + statementsMap.put(keyR2(r1, r2), entry); + } + return entry; + } + + SuperRelations getOrCreateSuperRelations(int r) { + SuperRelations entry = (SuperRelations)superRelationsMap.get(r); + if(entry == null) { + entry = new SuperRelations(r); + superRelationsMap.put(keyR(r), entry); + } + return entry; + } + + SuperTypes getOrCreateSuperTypes(int r) { + SuperTypes entry = (SuperTypes)superTypesMap.get(r); + if(entry == null) { + entry = new SuperTypes(r); + superTypesMap.put(keyR(r), entry); + } + return entry; + } + + TypeHierarchy getOrCreateTypeHierarchy(int r) { + TypeHierarchy entry = (TypeHierarchy)typeHierarchyMap.get(r); + if(entry == null) { + entry = new TypeHierarchy(r); + typeHierarchyMap.put(keyR(r), entry); + } + return entry; + } + + Types getOrCreateTypes(int r) { + Types entry = (Types)typesMap.get(r); + if(entry == null) { + entry = new Types(r); + typesMap.put(keyR(r), entry); + } + return entry; + } + + URIToResource getOrCreateURIToResource(String s) { + URIToResource entry = (URIToResource)uRIToResourceMap.get(s); + if(entry == null) { + entry = new URIToResource(s); + uRIToResourceMap.put(keyID(s), entry); + } + return entry; + } + + ValueQuery getOrCreateValueQuery(int r) { + ValueQuery entry = (ValueQuery)valueQueryMap.get(r); + if(entry == null) { + entry = new ValueQuery(r); + valueQueryMap.put(keyR(r), entry); + } + return entry; + } + } \ No newline at end of file diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl.java index 0b6f6ef83..e6dc252c4 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl.java @@ -148,6 +148,7 @@ class QueryCollectorImpl implements QueryProcessor.QueryCollector { } else { + entry.pruneParentSet(); support.setLevel(entry, parent.getLevel() + 1); } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryDeserializer.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryDeserializer.java new file mode 100644 index 000000000..0fe9b9c1e --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryDeserializer.java @@ -0,0 +1,227 @@ +package org.simantics.db.impl.query; + +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.simantics.db.ObjectResourceIdMap; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.impl.ClusterBase; +import org.simantics.db.impl.ClusterSupport; +import org.simantics.db.impl.ClusterTraitsBase; +import org.simantics.db.service.Bytes; +import org.slf4j.LoggerFactory; + +import gnu.trove.map.hash.TIntLongHashMap; + +public class QueryDeserializer { + + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(QueryDeserializer.class); + + QueryCache qc; + QuerySupport qs; + ClusterSupport cs; + + private byte[] bytes; + private int byteIndex; + + private TIntLongHashMap clusterKeys = new TIntLongHashMap(); + private Map ids = new HashMap(); + + public QueryDeserializer(QueryProcessor qp, byte[] bytes) { + this.qc = qp.cache; + this.qs = qp.querySupport; + this.cs = qs.getClusterSupport();; + this.bytes = bytes; + } + + public byte readByte() { + return bytes[byteIndex++]; + } + + public int readLE4() { + int result = Bytes.readLE4(bytes, byteIndex); + byteIndex += 4; + return result; + } + + public long readLE8() { + long result = Bytes.readLE8(bytes, byteIndex); + byteIndex += 8; + return result; + } + + public byte[] readBytes(int len) { + byte[] result = Arrays.copyOfRange(bytes, byteIndex, byteIndex+len); + byteIndex += len; + return result; + } + + public void readHeaders() { + int idsSize = readLE4(); + for(int i=0;i clazz = (Class)getClass().getClassLoader().loadClass(id + "Factory"); + QueryFactory qf = clazz.getDeclaredConstructor().newInstance(); + ids.put(key, qf); + } catch (ClassNotFoundException e) { + LOGGER.error("Error while resolving QueryFactory", e); + } catch (InstantiationException e) { + LOGGER.error("Error while resolving QueryFactory", e); + } catch (IllegalAccessException e) { + LOGGER.error("Error while resolving QueryFactory", e); + } catch (IllegalArgumentException e) { + LOGGER.error("Error while resolving QueryFactory", e); + } catch (InvocationTargetException e) { + LOGGER.error("Error while resolving QueryFactory", e); + } catch (NoSuchMethodException e) { + LOGGER.error("Error while resolving QueryFactory", e); + } catch (SecurityException e) { + LOGGER.error("Error while resolving QueryFactory", e); + } + } + int clusterKeysSize = readLE4(); + for(int i=0;i createChildMap() { + return qs.createChildMap(); + } + + AssertedPredicates readAssertedPredicates() throws DatabaseException { + int r = readResource(); + return qc.getOrCreateAssertedPredicates(r); + } + + AssertedStatements readAssertedStatements() throws DatabaseException { + int r1 = readResource(); + int r2 = readResource(); + return qc.getOrCreateAssertedStatements(r1, r2); + } + + ChildMap readChildMap() throws DatabaseException { + int r = readResource(); + return qc.getOrCreateChildMap(r); + } + + DirectObjects readDirectObjects() throws DatabaseException { + int r1 = readResource(); + int r2 = readResource(); + return qc.getOrCreateDirectObjects(r1, r2); + } + + DirectPredicates readDirectPredicates() throws DatabaseException { + int r = readResource(); + return qc.getOrCreateDirectPredicates(r); + } + + Objects readObjects() throws DatabaseException { + int r1 = readResource(); + int r2 = readResource(); + return qc.getOrCreateObjects(r1, r2); + } + + OrderedSet readOrderedSet() throws DatabaseException { + int r = readResource(); + return qc.getOrCreateOrderedSet(r); + } + + Predicates readPredicates() throws DatabaseException { + int r = readResource(); + return qc.getOrCreatePredicates(r); + } + + PrincipalTypes readPrincipalTypes() throws DatabaseException { + int r = readResource(); + return qc.getOrCreatePrincipalTypes(r); + } + + RelationInfoQuery readRelationInfoQuery() throws DatabaseException { + int r = readResource(); + return qc.getOrCreateRelationInfoQuery(r); + } + + Statements readStatements() throws DatabaseException { + int r1 = readResource(); + int r2 = readResource(); + return qc.getOrCreateStatements(r1, r2); + } + + SuperRelations readSuperRelations() throws DatabaseException { + int r = readResource(); + return qc.getOrCreateSuperRelations(r); + } + + SuperTypes readSuperTypes() throws DatabaseException { + int r = readResource(); + return qc.getOrCreateSuperTypes(r); + } + + TypeHierarchy readTypeHierarchy() throws DatabaseException { + int r = readResource(); + return qc.getOrCreateTypeHierarchy(r); + } + + Types readTypes() throws DatabaseException { + int r = readResource(); + return qc.getOrCreateTypes(r); + } + + URIToResource readURIToResource() throws DatabaseException { + String s = readString(); + return qc.getOrCreateURIToResource(s); + } + + ValueQuery readValueQuery() throws DatabaseException { + int r = readResource(); + return qc.getOrCreateValueQuery(r); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryFactory.java new file mode 100644 index 000000000..c4b3f9f9a --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryFactory.java @@ -0,0 +1,8 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public interface QueryFactory { + public CacheEntryBase read(QueryDeserializer deserializer) throws DatabaseException; + public T reference(QueryDeserializer deserializer) throws DatabaseException; +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryFactoryBase.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryFactoryBase.java new file mode 100644 index 000000000..a193ccec3 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryFactoryBase.java @@ -0,0 +1,25 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +abstract public class QueryFactoryBase implements QueryFactory { + + abstract protected CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException; + + public void readParents(QueryDeserializer deserializer, CacheEntryBase entry) throws DatabaseException { + int ps = deserializer.readLE4(); + for(int i=0;i getParents(QueryProcessor processor) { + public Collection getParents(QueryProcessor processor) { // TODO Auto-generated method stub return null; } @@ -227,7 +229,11 @@ abstract public class QueryIdentityHash extends THash { // TODO Auto-generated method stub return null; } - + + @Override + void pruneParentSet() { + } + }; /** diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryIdentityHashSet.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryIdentityHashSet.java index 3a7eb6182..ac2602fcb 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryIdentityHashSet.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryIdentityHashSet.java @@ -147,7 +147,25 @@ final public class QueryIdentityHashSet extends QueryIdentityHash implements Ite } } - + + final public void removeDiscardedReally() { + + tempDisableAutoCompaction(); + try { + + for(int i=0;i<_set.length;i++) { + CacheEntry entry = _set[i]; + if(entry != null && REMOVED != entry) { + if(entry.isDiscarded()) removeAt(i); + } + } + + } finally { + reenableAutoCompaction(false); + } + + } + /** * Creates an iterator over the values of the set. The iterator * supports element deletion. diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryListening.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryListening.java index 91200f1fc..e0b39d651 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryListening.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryListening.java @@ -415,7 +415,7 @@ public class QueryListening { @Override public void run() { - ListenerEntry entry = addedEntries.get(base); + ListenerEntry entry = addedEntries.remove(base); if(entry != null) entry.setLastKnown(result); } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryProcessor.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryProcessor.java index 6d9560940..f61c661d1 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryProcessor.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryProcessor.java @@ -32,6 +32,7 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import org.eclipse.core.runtime.Platform; import org.simantics.databoard.Bindings; import org.simantics.db.AsyncReadGraph; import org.simantics.db.DevelopmentKeys; @@ -42,6 +43,7 @@ import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.Statement; import org.simantics.db.VirtualGraph; +import org.simantics.db.common.ByteFileReader; import org.simantics.db.common.procedure.adapter.AsyncMultiProcedureAdapter; import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; @@ -68,9 +70,11 @@ import org.simantics.db.request.AsyncMultiRead; import org.simantics.db.request.ExternalRead; import org.simantics.db.request.MultiRead; import org.simantics.db.request.RequestFlags; +import org.simantics.db.service.Bytes; import org.simantics.layer0.Layer0; import org.simantics.utils.DataContainer; import org.simantics.utils.Development; +import org.simantics.utils.FileUtils; import org.simantics.utils.datastructures.Pair; import org.simantics.utils.datastructures.collections.CollectionUtils; import org.simantics.utils.datastructures.disposable.AbstractDisposable; @@ -1069,6 +1073,82 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap } + public synchronized void save() throws IOException { + + long start = System.nanoTime(); + + Collection caches = allCaches(new CacheCollectionResult()).toCollection(); + Map> cachesByCluster = new HashMap<>(); + for(CacheEntryBase entry : caches) { + String clazz = entry.classId(); + if(clazz == null) + continue; + long cluster = entry.cluster(this); + List queries = cachesByCluster.get(cluster); + if(queries == null) { + queries = new ArrayList<>(); + cachesByCluster.put(cluster, queries); + } + queries.add(entry); + } + + File workspace = Platform.getLocation().toFile(); + File dir = new File(workspace, "queryData"); + FileUtils.deleteAll(dir); + + dir.mkdir(); + + for(Long cluster : cachesByCluster.keySet()) { + + List queries = cachesByCluster.get(cluster); + QuerySerializer serializer = new QuerySerializer(this); + int count = 0; + int pos = serializer.writeUnknownSize(); + for(CacheEntryBase entry : queries) { + String clazz = entry.classId(); + if(clazz == null) + continue; + try { + entry.serialize(serializer); + count++; + } catch (IllegalStateException e) { + System.err.println(e.getMessage()); + } + } + serializer.setUnknownSize(pos, count); + + System.err.println(serializer.bytes().length + " bytes for cluster " + cluster); + FileUtils.writeFile(new File(dir, "" + cluster + ".queryData"), serializer.bytes()); + + } + + long end = System.nanoTime(); + + System.err.println("saved queries in " + 1e-6*(end-start) + "ms."); + + } + + public void restore() throws IOException { + + long start = System.nanoTime(); + + File workspace = Platform.getLocation().toFile(); + File dir = new File(workspace, "queryData"); + dir.mkdir(); + + for(File f : FileUtils.listFilesByExtension(dir, "queryData")) { + byte[] bytes = FileUtils.readFile(f); + QueryDeserializer qd = new QueryDeserializer(this, bytes); + qd.readHeaders(); + qd.readQueries(); + } + + long end = System.nanoTime(); + + System.err.println("restored queries in " + 1e-6*(end-start) + "ms."); + + } + boolean removeQuery(CacheEntry entry) { // This entry has been removed before. No need to do anything here. @@ -1760,6 +1840,12 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap } return result; } + + public long cluster(int resource) { + if(resource <= 0) + return 0; + return querySupport.getClusterId(resource); + } public void assertDone() { } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QuerySerializer.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QuerySerializer.java new file mode 100644 index 000000000..06b01407c --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QuerySerializer.java @@ -0,0 +1,136 @@ +package org.simantics.db.impl.query; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.simantics.db.impl.ClusterTraitsBase; + +import gnu.trove.list.array.TByteArrayList; +import gnu.trove.map.hash.TLongIntHashMap; +import gnu.trove.procedure.TLongIntProcedure; + +public class QuerySerializer { + + private QueryProcessor processor; + private QuerySupport querySupport; + private TByteArrayList bytes = new TByteArrayList(); + private TLongIntHashMap clusterKeys = new TLongIntHashMap(); + private Map ids = new HashMap(); + + public QuerySerializer(QueryProcessor processor) { + this.processor = processor; + this.querySupport = processor.querySupport; + } + + public int writeUnknownSize() { + int pos = bytes.size(); + bytes.add((byte)0); + bytes.add((byte)0); + bytes.add((byte)0); + bytes.add((byte)0); + return pos; + } + + public void setUnknownSize(int pos, int value) { + bytes.set(pos, (byte) (value & 0xFF)); + bytes.set(pos+1, (byte) ((value >>> 8) & 0xFF)); + bytes.set(pos+2, (byte) ((value >>> 16) & 0xFF)); + bytes.set(pos+3, (byte) ((value >>> 24) & 0xFF)); + } + + public void serializeId(String classId) { + Integer id = ids.get(classId); + if(id == null) { + id = ids.size() + 1; + ids.put(classId, id); + } + writeLE(id); + } + + public void addResource(int r) { + if(r < 0) { + writeLE(r); + } else { + long clusterId = querySupport.getClusterId(r); + int clusterKey = clusterKeys.get(clusterId); + if(clusterKey == 0) { + clusterKey = clusterKeys.size() + 1; + clusterKeys.put(clusterId, clusterKey); + } + int i = ClusterTraitsBase.createResourceKeyNoThrow(clusterKey, ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(r)); + writeLE(i); + } + } + + public void addString(String s) { + byte[] b = s.getBytes(); + writeLE(b.length); + bytes.add(b); + } + + public void add(byte b) { + bytes.add(b); + } + + public void add(byte[] bs) { + bytes.add(bs); + } + + public byte[] bytes() { + TByteArrayList header = new TByteArrayList(); + writeLE(header, ids.size()); + for(Entry entry : ids.entrySet()) { + String id = entry.getKey(); + writeLE(header, id.length()); + header.add(id.getBytes()); + writeLE(header, entry.getValue()); + } + + writeLE(header, clusterKeys.size()); + clusterKeys.forEachEntry(new TLongIntProcedure() { + + @Override + public boolean execute(long a, int b) { + writeLE(header, a); + writeLE(header, b); + return true; + } + + }); + + header.add(bytes.toArray()); + return header.toArray(); + } + + public void writeLE(int value) { + writeLE(bytes, value); + } + + public static void writeLE(TByteArrayList bytes, int value) { + bytes.add((byte) (value & 0xFF)); + bytes.add((byte) ((value >>> 8) & 0xFF)); + bytes.add((byte) ((value >>> 16) & 0xFF)); + bytes.add((byte) ((value >>> 24) & 0xFF)); + } + + public void writeLE(long value) { + writeLE(bytes, value); + } + + public static void writeLE(TByteArrayList bytes, long value) { + bytes.add((byte) (value & 0xFF)); + bytes.add((byte) ((value >>> 8) & 0xFF)); + bytes.add((byte) ((value >>> 16) & 0xFF)); + bytes.add((byte) ((value >>> 24) & 0xFF)); + bytes.add((byte) ((value >>> 32) & 0xFF)); + bytes.add((byte) ((value >>> 40) & 0xFF)); + bytes.add((byte) ((value >>> 48) & 0xFF)); + bytes.add((byte) ((value >>> 56) & 0xFF)); + } + + public QueryProcessor getQueryProcessor() { + return processor; + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QuerySupport.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QuerySupport.java index 3071c30c0..0a0a207fd 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QuerySupport.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QuerySupport.java @@ -13,17 +13,23 @@ package org.simantics.db.impl.query; import java.io.InputStream; +import org.simantics.db.ObjectResourceIdMap; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.VirtualGraph; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.ResourceNotFoundException; +import org.simantics.db.impl.ClusterSupport; import org.simantics.db.impl.graph.ReadGraphImpl; public interface QuerySupport extends ResourceTranslator { Session getSession(); - + + ClusterSupport getClusterSupport(); + + ObjectResourceIdMap createChildMap(); + boolean isImmutable(int id); long getClusterId(int id); int getId(Resource resource); diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ReadEntry.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ReadEntry.java index 8f547d22b..4fb5ed996 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ReadEntry.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ReadEntry.java @@ -214,4 +214,9 @@ public final class ReadEntry extends CacheEntryBase> implem except(throwable); } + @Override + public String classId() { + return null; + } + } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/RelationInfoQuery.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/RelationInfoQuery.java index cffd2984a..367e75f63 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/RelationInfoQuery.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/RelationInfoQuery.java @@ -100,4 +100,13 @@ public final class RelationInfoQuery extends UnaryQueryP { return RequestFlags.IMMEDIATE_UPDATE; } + @Override + public void serializeValue(QuerySerializer serializer) { + RelationInfo ri = getResult(); + serializer.addResource(ri.predicate); + serializer.add(ri.isFunctional ? (byte)1 : 0); + serializer.add(ri.isFinal ? (byte)1 : 0); + serializer.add(ri.isAsserted ? (byte)1 : 0); + } + } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/RelationInfoQueryFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/RelationInfoQueryFactory.java new file mode 100644 index 000000000..05adb56a7 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/RelationInfoQueryFactory.java @@ -0,0 +1,26 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.RelationInfo; +import org.simantics.db.exception.DatabaseException; + +public class RelationInfoQueryFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + RelationInfoQuery result = reference(deserializer); + int r = deserializer.readResource(); + int isFunctional = deserializer.readByte(); + int isFinal = deserializer.readByte(); + int isAsserted = deserializer.readByte(); + RelationInfo ri = new RelationInfo(r, isFunctional == 1, isFinal == 1, isAsserted == 1); + result.setResult(ri); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readRelationInfoQuery(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/StatementsFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/StatementsFactory.java new file mode 100644 index 000000000..7639235d6 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/StatementsFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class StatementsFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + Statements result = reference(deserializer); + IntArray ia = IntArray.deserialize(deserializer); + result.setResult(ia); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readStatements(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperRelations.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperRelations.java index 1f540062e..5c6e8e439 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperRelations.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperRelations.java @@ -21,7 +21,7 @@ import org.simantics.db.impl.procedure.InternalProcedure; import gnu.trove.procedure.TIntProcedure; import gnu.trove.set.hash.TIntHashSet; -public final class SuperRelations extends UnaryQueryP { +public final class SuperRelations extends UnaryQueryPIntSet { SuperRelations(final int resource) { super(resource); diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperRelationsFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperRelationsFactory.java new file mode 100644 index 000000000..9011b4606 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperRelationsFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class SuperRelationsFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + SuperRelations result = reference(deserializer); + IntSet ia = IntSet.deserialize(deserializer); + result.setResult(ia); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readSuperRelations(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperTypes.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperTypes.java index a02fda462..f3dc03e14 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperTypes.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperTypes.java @@ -17,7 +17,7 @@ import org.simantics.db.impl.procedure.InternalProcedure; import gnu.trove.procedure.TIntProcedure; -public final class SuperTypes extends UnaryQueryP { +public final class SuperTypes extends UnaryQueryPIntSet { SuperTypes(int resource) { super(resource); diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperTypesFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperTypesFactory.java new file mode 100644 index 000000000..edb82ef83 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperTypesFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class SuperTypesFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + SuperTypes result = reference(deserializer); + IntSet ia = IntSet.deserialize(deserializer); + result.setResult(ia); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readSuperTypes(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TypeHierarchy.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TypeHierarchy.java index 5c2be0c64..323bbd42d 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TypeHierarchy.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TypeHierarchy.java @@ -18,7 +18,7 @@ import org.simantics.db.procedure.ListenerBase; import gnu.trove.procedure.TIntProcedure; -public final class TypeHierarchy extends UnaryQueryP { +public final class TypeHierarchy extends UnaryQueryPIntSet { TypeHierarchy(int resource) { super(resource); diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TypeHierarchyFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TypeHierarchyFactory.java new file mode 100644 index 000000000..d8120b7f2 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TypeHierarchyFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class TypeHierarchyFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + TypeHierarchy result = reference(deserializer); + IntSet ia = IntSet.deserialize(deserializer); + result.setResult(ia); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readTypeHierarchy(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Types.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Types.java index a9fe36bc6..bb0d11a24 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Types.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Types.java @@ -19,7 +19,7 @@ import org.simantics.db.impl.procedure.InternalProcedure; import gnu.trove.procedure.TIntProcedure; -public final class Types extends UnaryQueryP { +public final class Types extends UnaryQueryPIntSet { Types(int resource) { super(resource); diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TypesFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TypesFactory.java new file mode 100644 index 000000000..014b0eecd --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TypesFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class TypesFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + Types result = reference(deserializer); + IntSet ia = IntSet.deserialize(deserializer); + result.setResult(ia); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readTypes(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/URIToResource.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/URIToResource.java index ec7ebeed7..9dae343e3 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/URIToResource.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/URIToResource.java @@ -144,4 +144,20 @@ public class URIToResource extends StringQuery> imple except(throwable); } + @Override + public long cluster(QueryProcessor processor) { + return 0; + } + + @Override + public void serializeKey(QuerySerializer serializer) { + serializer.addString(id); + } + + @Override + public void serializeValue(QuerySerializer serializer) { + Integer value = getResult(); + serializer.addResource(value); + } + } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/URIToResourceFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/URIToResourceFactory.java new file mode 100644 index 000000000..ca82ff647 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/URIToResourceFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class URIToResourceFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + URIToResource result = reference(deserializer); + int value = deserializer.readResource(); + result.setResult(value); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readURIToResource(); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/UnaryQuery.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/UnaryQuery.java index fd6cd7d87..fe24846aa 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/UnaryQuery.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/UnaryQuery.java @@ -15,6 +15,8 @@ import org.simantics.db.exception.DatabaseException; import org.simantics.db.impl.graph.ReadGraphImpl; import org.simantics.db.request.RequestFlags; +import gnu.trove.list.array.TByteArrayList; + public abstract class UnaryQuery extends CacheEntryBase implements Query { final public int id; @@ -68,4 +70,14 @@ public abstract class UnaryQuery extends CacheEntryBase im return graph.processor.isImmutable(id); } + @Override + public long cluster(QueryProcessor processor) { + return processor.cluster(id); + } + + @Override + public void serializeKey(QuerySerializer serializer) { + serializer.addResource(id); + } + } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/UnaryQueryPIntSet.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/UnaryQueryPIntSet.java new file mode 100644 index 000000000..cf824790a --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/UnaryQueryPIntSet.java @@ -0,0 +1,15 @@ +package org.simantics.db.impl.query; + +abstract public class UnaryQueryPIntSet extends UnaryQueryP { + + public UnaryQueryPIntSet(int r) { + super(r); + } + + @Override + public void serializeValue(QuerySerializer serializer) { + IntSet is = getResult(); + is.serialize(serializer); + } + +} diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ValueQuery.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ValueQuery.java index ad4017f9c..f04df9f68 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ValueQuery.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ValueQuery.java @@ -45,6 +45,17 @@ public final class ValueQuery extends UnaryQueryP { return value; } + + @Override + public void serializeValue(QuerySerializer serializer) { + byte[] result = getResult(); + if(result == null) { + serializer.writeLE(-1); + } else { + serializer.writeLE(result.length); + serializer.add(result); + } + } @Override public String toString() { diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ValueQueryFactory.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ValueQueryFactory.java new file mode 100644 index 000000000..4a746fda1 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ValueQueryFactory.java @@ -0,0 +1,21 @@ +package org.simantics.db.impl.query; + +import org.simantics.db.exception.DatabaseException; + +public class ValueQueryFactory extends QueryFactoryBase { + + @Override + public CacheEntryBase readKeyAndValue(QueryDeserializer deserializer) throws DatabaseException { + ValueQuery result = reference(deserializer); + byte[] bytes = deserializer.readByteArray(); + result.setResult(bytes); + result.setReady(); + return result; + } + + @Override + public T reference(QueryDeserializer deserializer) throws DatabaseException { + return (T)deserializer.readValueQuery(); + } + +} diff --git a/bundles/org.simantics.db.layer0/META-INF/MANIFEST.MF b/bundles/org.simantics.db.layer0/META-INF/MANIFEST.MF index ac53847a3..17fc2ed8c 100644 --- a/bundles/org.simantics.db.layer0/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.db.layer0/META-INF/MANIFEST.MF @@ -9,7 +9,6 @@ Require-Bundle: gnu.trove3;bundle-version="3.0.3", org.simantics.databoard;bundle-version="0.6.2";visibility:=reexport, org.simantics.db.services;bundle-version="1.1.0";visibility:=reexport, org.simantics.db.management;bundle-version="1.1.0", - org.apache.log4j;bundle-version="1.2.15", org.apache.commons.io;bundle-version="1.4.0", org.simantics.layer0;bundle-version="1.0.0";visibility:=reexport, org.simantics.graph.db;bundle-version="1.1.5";visibility:=reexport, diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/AbstractExpressionCompilationRequest.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/AbstractExpressionCompilationRequest.java index 1bcd91877..16f88a340 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/AbstractExpressionCompilationRequest.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/AbstractExpressionCompilationRequest.java @@ -179,7 +179,6 @@ implements Read> { b2.append('\n'); } SCLDatabaseException exception = new SCLDatabaseException(b.toString()+b2.toString(), b2.toString(), e.getErrors()); - LOGGER.info(exception.getMessage(), exception); throw exception; } catch(Throwable e) { // Should not happen! diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeStructureRequest.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeStructureRequest.java index 5d21ca56b..707fdbd0e 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeStructureRequest.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeStructureRequest.java @@ -7,174 +7,177 @@ import java.util.Map; import org.simantics.databoard.util.ObjectUtils; import org.simantics.db.ReadGraph; import org.simantics.db.common.request.ParametrizedPrimitiveRead; -import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.variable.Variables.NodeStructure; import org.simantics.db.procedure.Listener; import org.simantics.simulator.variable.exceptions.NodeManagerException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import gnu.trove.map.hash.THashMap; @SuppressWarnings("rawtypes") class NodeStructureRequest extends ParametrizedPrimitiveRead implements VariableNodeReadRunnable { - private Listener listener = null; - private NodeStructure value = Variables.PENDING_NODE_STRUCTURE; - private boolean wasRun = false; - - static class Probe implements Runnable { - - private VariableNode node; - public NodeStructure result; - - public Probe(VariableNode node) { - this.node = node; - } - - @SuppressWarnings("unchecked") - @Override - public void run() { - try { - result = NodeStructureRequest.get(node); - node.support.structureCache.put(node.node, result, 1000000000L); - } catch (NodeManagerException e) { - e.printStackTrace(); - } - } - - } - - public NodeStructureRequest(VariableNode node) { - super(node); - } - - @SuppressWarnings("unchecked") - @Override - public void register(ReadGraph graph, final Listener procedure) { - - if(procedure.isDisposed()) { - - // We are not listening - NodeStructure result = (NodeStructure)parameter.support.structureCache.get(parameter.node); - - if(result != null) { - // Return cached value immediately - procedure.execute(result); - } else { - NodeStructureRequest.Probe probe = new Probe(parameter); - parameter.support.manager.getRealm().asyncExec(probe); - if(probe.result != null) { - procedure.execute(probe.result); - } else { - procedure.execute(Variables.PENDING_NODE_STRUCTURE); - } - } - - return; - - } - - // We need to listen - listener = procedure; - // Register listening - parameter.support.manager.addNodeListener(parameter.node, this); - synchronized(this) { - if(wasRun) { - procedure.execute(value); - } else { - NodeStructure result = (NodeStructure)parameter.support.structureCache.get(parameter.node); - if(result != null) { - procedure.execute(result); - } else { - procedure.execute(Variables.PENDING_NODE_STRUCTURE); - } - } - } - - } - - static class NodeListener implements VariableNodeReadRunnable { - - private VariableNode node; - private NodeStructureRequest request; - - public NodeListener(VariableNode node, NodeStructureRequest request) { - this.node = node; - this.request = request; - } - - @SuppressWarnings("unchecked") - @Override - public void run() { - node.support.manager.addNodeListener(node.node, request); - } - - } - - @SuppressWarnings("unchecked") - @Override - public void unregistered() { - parameter.support.manager.removeNodeListener(parameter.node, this); - parameter.support.structureCache.removeListening(parameter.node); - listener = null; - } - - @SuppressWarnings("unchecked") - public static NodeStructure get(VariableNode parameter) throws NodeManagerException { - List children = parameter.support.manager.getChildren(parameter.node); - List properties = parameter.support.manager.getProperties(parameter.node); - Map childMap = Collections.emptyMap(); - Map propertyMap = childMap; - if(!children.isEmpty()) { - childMap = new THashMap<>(children.size()); - for(Object o : children) { - String name = parameter.support.manager.getName(o); - childMap.put(name, o); - } - } - if(!properties.isEmpty()) { - propertyMap = new THashMap<>(properties.size()); - for(Object o : properties) { - String name = parameter.support.manager.getName(o); - propertyMap.put(name, o); - } - } - return new NodeStructure(childMap, propertyMap); - } - - @SuppressWarnings("unchecked") - @Override - public synchronized void run() { - try { - // Cache this value with infinite cache time since we are listening - NodeStructure newValue = get(parameter); - if (wasRun && ObjectUtils.objectEquals(value, newValue)) { - //System.out.println("CACHE VALUE MATCH (" + newValue + ") for " + node.node); - return; - } - value = newValue; - parameter.support.structureCache.put(parameter.node, value); - } catch (Throwable e) { - // Must catch everything to prevent DB client from getting stuck. - Logger.defaultLogError(e); - // Invoke the exception method of the listener - Listener listener = this.listener; - if (listener != null) listener.exception(new DatabaseException("External data access error", e)); - wasRun = true; - return; - } - - // Must always invoke an existing listener, regardless of earlier errors. - Listener listener = this.listener; - if (listener != null) { - listener.execute(value); - } - wasRun = true; - } - - @Override - public String toString() { - return "NodeStructureRequest.run @ " + System.identityHashCode(this); - } + private static final Logger LOGGER = LoggerFactory.getLogger(NodeStructureRequest.class); + + private Listener listener = null; + private NodeStructure value = Variables.PENDING_NODE_STRUCTURE; + private boolean wasRun = false; + + static class Probe implements Runnable { + + private VariableNode node; + public NodeStructure result; + + public Probe(VariableNode node) { + this.node = node; + } + + @SuppressWarnings("unchecked") + @Override + public void run() { + try { + result = NodeStructureRequest.get(node); + node.support.structureCache.put(node.node, result, 1000000000L); + } catch (NodeManagerException e) { + e.printStackTrace(); + } + } + + } + + public NodeStructureRequest(VariableNode node) { + super(node); + } + + @SuppressWarnings("unchecked") + @Override + public void register(ReadGraph graph, final Listener procedure) { + + if(procedure.isDisposed()) { + + // We are not listening + NodeStructure result = (NodeStructure)parameter.support.structureCache.get(parameter.node); + + if(result != null) { + // Return cached value immediately + procedure.execute(result); + } else { + NodeStructureRequest.Probe probe = new Probe(parameter); + parameter.support.manager.getRealm().asyncExec(probe); + if(probe.result != null) { + procedure.execute(probe.result); + } else { + procedure.execute(Variables.PENDING_NODE_STRUCTURE); + } + } + + return; + + } + + // We need to listen + listener = procedure; + // Register listening + parameter.support.manager.addNodeListener(parameter.node, this); + synchronized(this) { + if(!wasRun) { + NodeStructure result = (NodeStructure)parameter.support.structureCache.get(parameter.node); + if(result != null) { + procedure.execute(result); + } else { + procedure.execute(Variables.PENDING_NODE_STRUCTURE); + } + } + } + + } + + static class NodeListener implements VariableNodeReadRunnable { + + private VariableNode node; + private NodeStructureRequest request; + + public NodeListener(VariableNode node, NodeStructureRequest request) { + this.node = node; + this.request = request; + } + + @SuppressWarnings("unchecked") + @Override + public void run() { + node.support.manager.addNodeListener(node.node, request); + } + + } + + @SuppressWarnings("unchecked") + @Override + public void unregistered() { + parameter.support.manager.removeNodeListener(parameter.node, this); + parameter.support.structureCache.removeListening(parameter.node); + listener = null; + } + + @SuppressWarnings("unchecked") + public static NodeStructure get(VariableNode parameter) throws NodeManagerException { + List children = parameter.support.manager.getChildren(parameter.node); + List properties = parameter.support.manager.getProperties(parameter.node); + Map childMap = Collections.emptyMap(); + Map propertyMap = childMap; + if(!children.isEmpty()) { + childMap = new THashMap<>(children.size()); + for(Object o : children) { + String name = parameter.support.manager.getName(o); + childMap.put(name, o); + } + } + if(!properties.isEmpty()) { + propertyMap = new THashMap<>(properties.size()); + for(Object o : properties) { + String name = parameter.support.manager.getName(o); + propertyMap.put(name, o); + } + } + return new NodeStructure(childMap, propertyMap); + } + + @SuppressWarnings("unchecked") + @Override + public synchronized void run() { + try { + // Cache this value with infinite cache time since we are listening + NodeStructure newValue = get(parameter); + if (wasRun && ObjectUtils.objectEquals(value, newValue)) { + //System.out.println("CACHE VALUE MATCH (" + newValue + ") for " + node.node); + return; + } + value = newValue; + parameter.support.structureCache.put(parameter.node, value); + } catch (Throwable e) { + // Must catch everything to prevent DB client from getting stuck. + LOGGER.error("Error while computing node structure", e); + // Invoke the exception method of the listener + Listener listener = this.listener; + if (listener != null) { + listener.exception(new DatabaseException("External data access error", e)); + wasRun = true; + } + return; + } + + // Must always invoke an existing listener, regardless of earlier errors. + Listener listener = this.listener; + if (listener != null) { + listener.execute(value); + wasRun = true; + } + } + + @Override + public String toString() { + return "NodeStructureRequest.run @ " + System.identityHashCode(this); + } } \ No newline at end of file diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java index 140ee8fa0..b44f16b30 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java @@ -110,9 +110,7 @@ class NodeValueRequest extends ParametrizedPrimitiveRead listener = this.listener; - if (listener != null) listener.exception(new DatabaseException("External data access error", e)); - wasRun = true; + if (listener != null) { + listener.exception(new DatabaseException("External data access error", e)); + wasRun = true; + } return; } // Must always invoke an existing listener, regardless of earlier errors. @@ -228,8 +228,8 @@ class NodeValueRequest extends ParametrizedPrimitiveRead> getCommands = new HashMap>(); final private Map> listCommands = new HashMap>(); final private Map> execCommands = new HashMap>(); @@ -106,6 +109,21 @@ public class DebugSupportImpl implements DebugSupport { }); + listCommands.put("queryData", new FunctionImpl3() { + + @Override + public String apply(WriteGraph graph, File file, String args) { + try { + getSession(graph).queryProvider2.save(); + return "Saved queries"; + } catch (IOException e) { + LOGGER.error("Error while saving queries", e); + return e.getMessage(); + } + } + + }); + listCommands.put("queryActivity", new FunctionImpl3() { @Override diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ObjectResourceMap.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ObjectResourceMap.java index 8b26442d8..02daf860e 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ObjectResourceMap.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ObjectResourceMap.java @@ -214,5 +214,5 @@ final class ObjectResourceMap implements Map, ObjectResourceIdMa public int getId(T t) { return backend.get(t); } - + } \ No newline at end of file diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/QuerySupportImpl.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/QuerySupportImpl.java index eea97e2e0..0febcea1b 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/QuerySupportImpl.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/QuerySupportImpl.java @@ -5,6 +5,7 @@ import java.io.InputStream; import java.util.Collection; import java.util.function.Consumer; +import org.simantics.db.ObjectResourceIdMap; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.Statement; @@ -83,7 +84,17 @@ public class QuerySupportImpl implements QuerySupport { public ResourceSupport getSupport() { return resourceSupport; } - + + @Override + public ClusterSupport getClusterSupport() { + return clusterSupport; + } + + @Override + public ObjectResourceIdMap createChildMap() { + return new ObjectResourceMap(session); + } + @Override public Statement getStatement(int s, int p, int o) { return getStatement(null, s, p, o); diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplDb.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplDb.java index 0178e805f..2b7f2da33 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplDb.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplDb.java @@ -93,6 +93,9 @@ final public class SessionImplDb extends SessionImplSocket { serviceLocator.registerService(QuerySupport.class, querySupport); queryProvider2 = new QueryProcessor(getAmountOfQueryThreads(), querySupport, sessionThreads); + + if("true".equals(System.getProperty("org.simantics.db.persistQueries"))) + queryProvider2.restore(); writeSupport = new WriteSupportImpl(this); serviceLocator.registerService(WriteSupport.class, writeSupport); diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/XSupportImpl.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/XSupportImpl.java index 058706686..7a9be0480 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/XSupportImpl.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/XSupportImpl.java @@ -1,5 +1,7 @@ package fi.vtt.simantics.procore.internal; +import java.io.IOException; + import org.simantics.db.Database; import org.simantics.db.Resource; import org.simantics.db.Session; @@ -175,5 +177,14 @@ public class XSupportImpl implements XSupport { ClusterImpl clusterImpl = session.clusterTable.getClusterByClusterUIDOrMakeProxy(clusterUID); return clusterImpl.isLoaded(); } - + + @Override + public void saveQueries() throws DatabaseException { + try { + session.queryProvider2.save(); + } catch (IOException e) { + throw new DatabaseException(e); + } + } + } diff --git a/bundles/org.simantics.db.server/META-INF/MANIFEST.MF b/bundles/org.simantics.db.server/META-INF/MANIFEST.MF index 7e9cf890e..bd2c64b31 100644 --- a/bundles/org.simantics.db.server/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.db.server/META-INF/MANIFEST.MF @@ -11,8 +11,6 @@ Bundle-RequiredExecutionEnvironment: JavaSE-11 Import-Package: gnu.trove.impl.hash, gnu.trove.iterator, gnu.trove.map.hash, - org.apache.log4j, - org.apache.log4j.spi, org.eclipse.core.runtime, org.osgi.framework;version="1.3.0", org.simantics.db, diff --git a/bundles/org.simantics.db/src/org/simantics/db/RelationInfo.java b/bundles/org.simantics.db/src/org/simantics/db/RelationInfo.java index fb4c4820a..168816ed9 100644 --- a/bundles/org.simantics.db/src/org/simantics/db/RelationInfo.java +++ b/bundles/org.simantics.db/src/org/simantics/db/RelationInfo.java @@ -11,8 +11,6 @@ *******************************************************************************/ package org.simantics.db; - - final public class RelationInfo { public static final RelationInfo[] NONE = new RelationInfo[0]; @@ -27,7 +25,7 @@ final public class RelationInfo { this.isFinal = isFinal; this.isAsserted = isAsserted; } - + @Override public String toString() { return "RelationInfo[predicate=" + predicate + ", isFunctional=" + isFunctional + ", isFinal=" + isFinal + ", isAsserted=" + isAsserted + "]"; diff --git a/bundles/org.simantics.db/src/org/simantics/db/service/XSupport.java b/bundles/org.simantics.db/src/org/simantics/db/service/XSupport.java index cf9e96e78..bab69074e 100644 --- a/bundles/org.simantics.db/src/org/simantics/db/service/XSupport.java +++ b/bundles/org.simantics.db/src/org/simantics/db/service/XSupport.java @@ -162,5 +162,7 @@ public interface XSupport { public boolean rolledback(); public boolean isClusterLoaded(ClusterUID clusterUID) throws DatabaseException; - + + public void saveQueries() throws DatabaseException; + } diff --git a/bundles/org.simantics.debug.graphical/scl/Simantics/GraphicalDebugger.scl b/bundles/org.simantics.debug.graphical/scl/Simantics/GraphicalDebugger.scl index 7a23274c4..0542beb1d 100644 --- a/bundles/org.simantics.debug.graphical/scl/Simantics/GraphicalDebugger.scl +++ b/bundles/org.simantics.debug.graphical/scl/Simantics/GraphicalDebugger.scl @@ -1,6 +1,6 @@ import "Simantics/DB" -importJava "org.simantics.debug.graphical.DebuggerCanvas" where +importJava "org.simantics.debug.graphical.DebuggerCanvasProxy" where data GraphDebugger setStatementFilter :: GraphDebugger -> (Statement -> Boolean) -> () diff --git a/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/DebuggerCanvasProxy.java b/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/DebuggerCanvasProxy.java new file mode 100644 index 000000000..bf7a73887 --- /dev/null +++ b/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/DebuggerCanvasProxy.java @@ -0,0 +1,32 @@ +package org.simantics.debug.graphical; + +import org.simantics.db.Resource; +import org.simantics.scl.runtime.function.Function; + +/** + * Simantics/GraphicalDebugger SCL API to avoid undesired AWT + * toolkit initialization. + * + * @author Tuukka Lehtonen + */ +public class DebuggerCanvasProxy { + + DebuggerCanvas canvas; + + public void setStatementFilter(@SuppressWarnings("rawtypes") Function statementFilter) { + canvas.setStatementFilter(statementFilter); + } + + public void removeStatementFilter() { + canvas.removeStatementFilter(); + } + + public void addResource(Resource resource) { + canvas.addResource(resource); + } + + public DebuggerCanvasProxy(DebuggerCanvas canvas) { + this.canvas = canvas; + } + +} diff --git a/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/GraphicalDebugger.java b/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/GraphicalDebugger.java index 9091a27f9..81844e4ae 100644 --- a/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/GraphicalDebugger.java +++ b/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/GraphicalDebugger.java @@ -11,7 +11,7 @@ import javax.swing.JFrame; public class GraphicalDebugger { - public static DebuggerCanvas newGraphDebugger() { + public static DebuggerCanvasProxy newGraphDebugger() { final JFrame frame = new JFrame(); frame.setTitle("Graph debugger"); Toolkit tk = Toolkit.getDefaultToolkit(); @@ -53,7 +53,7 @@ public class GraphicalDebugger { }); frame.setVisible(true); - return canvas; + return new DebuggerCanvasProxy(canvas); } } diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteLine.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteLine.java index 2011bfa28..225c4abfe 100644 --- a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteLine.java +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteLine.java @@ -113,10 +113,17 @@ public class RouteLine implements RouteNode, Serializable { out.print(" HOR"); else out.print(" VER"); + if (hidden) + out.print(" HIDDEN"); + out.print(" @ " + position); for(RoutePoint point : points) { out.print(" ("+point.x+","+point.y+")"); } out.print(" (data=" + data + ")"); + if (nextTransient != null) + out.print(" (next transient line=" + nextTransient.getData() + ")"); + if (terminal != null) + out.print(" (terminal=" + terminal.getData() + ")"); out.println(); } diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/segments/Segment.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/segments/Segment.java index b283cb4ed..4e4280c0a 100644 --- a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/segments/Segment.java +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/segments/Segment.java @@ -28,4 +28,9 @@ public class Segment { public boolean isDegenerated() { return p1.getX() == p2.getX() && p1.getY() == p2.getY(); } + + @Override + public String toString() { + return String.format("(%f, %f) (%f, %f)", p1.getX(), p1.getY(), p2.getX(), p2.getY()); + } } diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/splitting/SplittedRouteGraph.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/splitting/SplittedRouteGraph.java index ae79dc019..8f7f71a29 100644 --- a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/splitting/SplittedRouteGraph.java +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/splitting/SplittedRouteGraph.java @@ -1,13 +1,17 @@ package org.simantics.diagram.connection.splitting; -import gnu.trove.set.hash.THashSet; - +import java.awt.geom.Line2D; import java.awt.geom.Point2D; +import java.util.ArrayList; import org.simantics.diagram.connection.RouteGraph; import org.simantics.diagram.connection.RouteLine; import org.simantics.diagram.connection.RouteNode; +import org.simantics.diagram.connection.RoutePoint; import org.simantics.diagram.connection.RouteTerminal; +import org.simantics.diagram.connection.segments.Segment; + +import gnu.trove.set.hash.THashSet; public class SplittedRouteGraph { public final RouteLine splitLine; @@ -91,7 +95,75 @@ public class SplittedRouteGraph { } } - /** + public static final class PickResult { + /** + * The connection route line nearest to {@link #pickPoint}. + */ + public final RouteLine nearestLine; + /** + * Original pick point in canvas coordinates. + */ + public final Point2D pickPoint; + /** + * Intersection point in canvas coordinates of {@link #nearestLine} and + * perpendicular line from {@link #pickPoint} to {@link #nearestLine}. + */ + public final Point2D intersectionPoint; + + public PickResult(RouteLine nearestLine, Point2D pickPoint, Point2D intersectionPoint) { + this.nearestLine = nearestLine; + this.pickPoint = pickPoint; + this.intersectionPoint = intersectionPoint; + } + } + + public static PickResult pickNearestLine(RouteGraph rg, double x, double y) { + Segment nearestSegment = null; + RouteLine nearestLine = null; + + ArrayList segments = new ArrayList<>(); + double minDistanceSq = Double.MAX_VALUE; + for (RouteLine line : rg.getAllLines()) { + segments.clear(); + line.collectSegments(segments); + for (Segment segment : segments) { + RoutePoint p1 = segment.p1; + RoutePoint p2 = segment.p2; + double distanceSq = Line2D.ptSegDistSq(p1.getX(), p1.getY(), p2.getX(), p2.getY(), x, y); + if (distanceSq < minDistanceSq) { + minDistanceSq = distanceSq; + nearestSegment = segment; + nearestLine = line; + } + } + } + + if (nearestSegment == null) + return null; + + RoutePoint p1 = nearestSegment.p1; + RoutePoint p2 = nearestSegment.p2; + Point2D p = pointToLineIntersection(p1.getX(), p1.getY(), p2.getX(), p2.getY(), x, y); + return new PickResult(nearestLine, new Point2D.Double(x, y), p); + } + + private static Point2D pointToLineIntersection(double x1, double y1, double x2, double y2, double px, double py) { + double d = Math.pow(x2 - x1, 2.0) + Math.pow(y2 - y1, 2.0); + if (d == 0) { + return new Point2D.Double(x1, y1); + } else { + double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / d; + if (u > 1.0) { + return new Point2D.Double(x2, y2); + } else if (u <= 0.0) { + return new Point2D.Double(x1, y1); + } else { + return new Point2D.Double(x2 * u + x1 * (1.0-u), (y2 * u + y1 * (1.0- u))); + } + } + } + + /** * @param point * @param line * @return the specified point instance snapped to the specified line diff --git a/bundles/org.simantics.diagram.profile/META-INF/MANIFEST.MF b/bundles/org.simantics.diagram.profile/META-INF/MANIFEST.MF index ffc1fac85..60816536a 100644 --- a/bundles/org.simantics.diagram.profile/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.diagram.profile/META-INF/MANIFEST.MF @@ -14,7 +14,8 @@ Require-Bundle: org.simantics.browsing.ui.swt;bundle-version="1.1.0", org.simantics.views.swt;bundle-version="1.0.0", org.simantics.views.swt.client;bundle-version="1.0.0", org.simantics.views.ontology;bundle-version="1.0.0", - org.simantics.selectionview;bundle-version="1.0.0" + org.simantics.selectionview;bundle-version="1.0.0", + org.slf4j.api Import-Package: org.simantics.views Bundle-Vendor: Semantum Oy Export-Package: org.simantics.diagram.profile.request diff --git a/bundles/org.simantics.diagram.profile/src/org/simantics/diagram/profile/view/CreateGroupAction.java b/bundles/org.simantics.diagram.profile/src/org/simantics/diagram/profile/view/CreateGroupAction.java index 58cd82b0e..cbe77333f 100644 --- a/bundles/org.simantics.diagram.profile/src/org/simantics/diagram/profile/view/CreateGroupAction.java +++ b/bundles/org.simantics.diagram.profile/src/org/simantics/diagram/profile/view/CreateGroupAction.java @@ -7,13 +7,16 @@ import org.simantics.db.WriteGraph; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; -import org.simantics.diagram.Logger; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.layer0.Layer0; import org.simantics.operation.Layer0X; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class CreateGroupAction extends ModelledActionImpl { + private static final Logger LOGGER = LoggerFactory.getLogger(CreateGroupAction.class); + public CreateGroupAction(Resource configuration) { super(configuration); } @@ -49,9 +52,7 @@ public class CreateGroupAction extends ModelledActionImpl { }); } catch (DatabaseException e) { - - Logger.defaultLogError(e); - + LOGGER.error("CreateGroupAction failed", e); } } diff --git a/bundles/org.simantics.diagram.profile/src/org/simantics/diagram/profile/view/CreateProfileAction.java b/bundles/org.simantics.diagram.profile/src/org/simantics/diagram/profile/view/CreateProfileAction.java index 656159abf..c0fdb11e3 100644 --- a/bundles/org.simantics.diagram.profile/src/org/simantics/diagram/profile/view/CreateProfileAction.java +++ b/bundles/org.simantics.diagram.profile/src/org/simantics/diagram/profile/view/CreateProfileAction.java @@ -8,12 +8,15 @@ import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.common.utils.OrderedSetUtils; import org.simantics.db.exception.DatabaseException; -import org.simantics.diagram.Logger; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.layer0.Layer0; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class CreateProfileAction extends ModelledActionImpl { + private static final Logger LOGGER = LoggerFactory.getLogger(CreateProfileAction.class); + public CreateProfileAction(Resource configuration) { super(configuration); } @@ -51,9 +54,7 @@ public class CreateProfileAction extends ModelledActionImpl { }); } catch (DatabaseException e) { - - Logger.defaultLogError(e); - + LOGGER.error("CreateProfileAction failed", e); } } diff --git a/bundles/org.simantics.diagram.profile/src/org/simantics/diagram/profile/view/CreateStyleAction.java b/bundles/org.simantics.diagram.profile/src/org/simantics/diagram/profile/view/CreateStyleAction.java index de0734156..6cda70f2d 100644 --- a/bundles/org.simantics.diagram.profile/src/org/simantics/diagram/profile/view/CreateStyleAction.java +++ b/bundles/org.simantics.diagram.profile/src/org/simantics/diagram/profile/view/CreateStyleAction.java @@ -7,13 +7,16 @@ import org.simantics.db.WriteGraph; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; -import org.simantics.diagram.Logger; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.layer0.Layer0; import org.simantics.operation.Layer0X; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class CreateStyleAction extends ModelledActionImpl { + private static final Logger LOGGER = LoggerFactory.getLogger(CreateStyleAction.class); + public CreateStyleAction(Resource configuration) { super(configuration); } @@ -49,9 +52,7 @@ public class CreateStyleAction extends ModelledActionImpl { }); } catch (DatabaseException e) { - - Logger.defaultLogError(e); - + LOGGER.error("CreateStyleAction failed", e); } } diff --git a/bundles/org.simantics.diagram/META-INF/MANIFEST.MF b/bundles/org.simantics.diagram/META-INF/MANIFEST.MF index 56776f834..92e4d84ae 100644 --- a/bundles/org.simantics.diagram/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.diagram/META-INF/MANIFEST.MF @@ -18,7 +18,6 @@ Require-Bundle: org.simantics.utils.thread.swt, org.simantics.diagram.ontology;bundle-version="1.0.0";visibility:=reexport, org.simantics.structural.ontology;bundle-version="1.0.0", org.simantics.layer0.utils;bundle-version="[1.0.0,2.0.0)", - org.apache.log4j;bundle-version="1.2.15", org.simantics.threadlog;bundle-version="1.0.0";resolution:=optional, org.simantics.graph;bundle-version="1.1.5", org.simantics.graph.db;bundle-version="1.1.5", diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/LogManager.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/LogManager.java deleted file mode 100644 index a4e1eab87..000000000 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/LogManager.java +++ /dev/null @@ -1,151 +0,0 @@ -/******************************************************************************* - * 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.diagram; - -import java.util.Properties; - -import org.apache.log4j.Hierarchy; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; -import org.apache.log4j.spi.LoggerFactory; -import org.apache.log4j.spi.RootLogger; - -/** - * This class encapsulates a Log4J Hierarchy and centralizes all Logger access. - */ -public class LogManager { - - private Hierarchy hierarchy; - - /** - * Creates a new LogManager. Saves the log and state location. - * Creates a new Hierarchy and add a new EventListener to it. - * Configure the hierarchy with the properties passed. Add this object to - * the list of active log managers. - * - * @param properties log configuration properties - */ - public LogManager(Properties properties) { - this.hierarchy = new Hierarchy(new RootLogger(Level.DEBUG)); - new PropertyConfigurator().doConfigure(properties, this.hierarchy); - } - - /** - * Checks if this PluginLogManager is disabled for this level. - * - * @param level level value - * @return boolean true if it is disabled - */ - public boolean isDisabled(int level) { - return this.hierarchy.isDisabled(level); - } - - /** - * Enable logging for logging requests with level l or higher. By default - * all levels are enabled. - * - * @param level level object - */ - public void setThreshold(Level level) { - this.hierarchy.setThreshold(level); - } - - /** - * The string version of setThreshold(Level level) - * - * @param level level string - */ - public void setThreshold(String level) { - this.hierarchy.setThreshold(level); - } - - /** - * Get the repository-wide threshold. - * - * @return Level - */ - public Level getThreshold() { - return this.hierarchy.getThreshold(); - } - - /** - * Returns a new logger instance named as the first parameter using the - * default factory. If a logger of that name already exists, then it will be - * returned. Otherwise, a new logger will be instantiated and then linked - * with its existing ancestors as well as children. - * - * @param clazz the class to get the logger for - * @return Logger - */ - public Logger getLogger(Class clazz) { - return this.hierarchy.getLogger(clazz.getName()); - } - - /** - * Returns a new logger instance named as the first parameter using the - * default factory. If a logger of that name already exists, then it will be - * returned. Otherwise, a new logger will be instantiated and then linked - * with its existing ancestors as well as children. - * - * @param name logger name - * @return Logger - */ - public Logger getLogger(String name) { - return this.hierarchy.getLogger(name); - } - - /** - * The same as getLogger(String name) but using a factory instance instead - * of a default factory. - * - * @param name logger name - * @param factory factory instance - * @return Logger - */ - public Logger getLogger(String name, LoggerFactory factory) { - return this.hierarchy.getLogger(name, factory); - } - - /** - * Returns the root of this hierarchy. - * - * @return Logger - */ - public Logger getRootLogger() { - return this.hierarchy.getRootLogger(); - } - - /** - * Checks if this logger exists. - * - * @return Logger - */ - public Logger exists(String name) { - return this.hierarchy.exists(name); - } - - /** - * Disposes the logger hierarchy - */ - public void shutdown() { - this.hierarchy.shutdown(); - } - - /** - * Resets configuration values to its defaults. - */ - public void resetConfiguration() { - this.hierarchy.resetConfiguration(); - } - -} \ No newline at end of file diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/Logger.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/Logger.java deleted file mode 100644 index ad93cb85b..000000000 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/Logger.java +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************* - * 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.diagram; - -import java.util.Properties; - -public class Logger { - public static final boolean ECHO = false; - public static final Properties defaultProperties = new Properties(); - static { - defaultProperties.put("log4j.rootCategory", "ERROR, default"); - defaultProperties.put("log4j.appender.default", "org.apache.log4j.FileAppender"); - defaultProperties.put("log4j.appender.default.File", "diagram.log"); - defaultProperties.put("log4j.appender.default.append", "false"); - defaultProperties.put("log4j.appender.default.layout", "org.apache.log4j.PatternLayout"); - defaultProperties.put("log4j.appender.default.layout.ConversionPattern", "%-6r [%15.15t] %-5p %30.30c - %m%n"); - } - private static LogManager defaultLogManager = new LogManager(defaultProperties); - private static final Logger defaultErrorLogger = new Logger(LogManager.class); - private org.apache.log4j.Logger logger; - Logger(Class clazz) { - logger = defaultLogManager.getLogger(clazz); - } - - /** - * Log a trace event. - * - * @param message message of the trace - * @param exception the exception, or null - */ - public void logTrace(String message, Throwable exception) { - // Errors are much more useful with a stack trace! - if (exception == null) { - exception = new RuntimeException(); - } - logger.trace(message, exception); - } - - /** - * Log an info event. - * - * @param message message of the info - * @param exception the exception, or null - */ - public void logInfo(String message, Throwable exception) { - // Errors are much more useful with a stack trace! - if (exception == null) { - exception = new RuntimeException(); - } - logger.info(message, exception); - } - - /** - * Log an error event. - * - * @param message message of the error - * @param exception the exception, or null - */ - public void logError(String message, Throwable exception) { - // Errors are much more useful with a stack trace! - if (exception == null) { - exception = new RuntimeException(); - } - logger.error(message, exception); - } - - public static Logger getDefault() { - return defaultErrorLogger; - } - - public static LogManager getDefaultLogManager() { - return defaultLogManager; - } - public static void defaultLogError(Throwable exception) { - getDefault().logError(exception.getLocalizedMessage(), exception); - if(ECHO) exception.printStackTrace(); - } - public static void defaultLogError(String message) { - getDefault().logError(message, null); - if(ECHO) - System.err.println(message); - } - public static void defaultLogError(String message, Throwable exception) { - getDefault().logError(message, exception); - if(ECHO) - System.err.println(message); - } - public static void defaultLogInfo(String message) { - getDefault().logInfo(message, null); - if(ECHO) - System.err.println(message); - } - public static void defaultLogTrace(String message) { - getDefault().logTrace(message, null); - if(ECHO) - System.err.println(message); - } -} diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/export/ExportDiagramPdf.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/export/ExportDiagramPdf.java index 23cb9f970..25e72d984 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/export/ExportDiagramPdf.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/export/ExportDiagramPdf.java @@ -183,8 +183,14 @@ public class ExportDiagramPdf implements ExportClass { ThreadUtils.syncExec(workerThread, new Runnable() { @Override public void run() { - try { + try { cctx.getDefaultHintContext().setHint(Hints.KEY_PAGE_DESC, _marginaaliViiva); + if (!fitDiagramContentsToPageMargins) { + // Prevent PDF printing from drawing page borders if the + // print area is fitted directly to the page size. + // This avoids unwanted black half-visible edges. + cctx.getDefaultHintContext().setHint(Hints.KEY_DISPLAY_PAGE, false); + } String bottomLabel = diagramName; if ( drawingTemplate != null && activeProfileEntries.contains(TMPL.DrawingTemplate) ) bottomLabel = null; diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/flag/FlagUtil.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/flag/FlagUtil.java index d38a301da..e53f4b636 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/flag/FlagUtil.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/flag/FlagUtil.java @@ -176,6 +176,17 @@ public final class FlagUtil { * @throws DatabaseException */ public static Resource join(WriteGraph g, Resource flag, Resource otherFlag) throws DatabaseException { + return join(g, flag, otherFlag, true); + } + + /** + * @param g + * @param flag + * @param otherFlag + * @return the created DIA.ConnectionJoin instance + * @throws DatabaseException + */ + public static Resource join(WriteGraph g, Resource flag, Resource otherFlag, boolean activateDiagramMapping) throws DatabaseException { DiagramResource DIA = DiagramResource.getInstance(g); StructuralResource2 STR = StructuralResource2.getInstance(g); Resource connectionJoin = g.newResource(); @@ -184,14 +195,24 @@ public final class FlagUtil { g.claim(connectionJoin, DIA.JoinsFlag, flag); g.claim(connectionJoin, DIA.JoinsFlag, otherFlag); - IActivationManager manager = g.getService(IActivationManager.class); - for(Resource diagram : OrderedSetUtils.getSubjects(g, flag)) - manager.activateOnce(g, diagram); - for(Resource diagram : OrderedSetUtils.getSubjects(g, otherFlag)) - manager.activateOnce(g, diagram); + if (activateDiagramMapping) { + activateMappingForParentDiagramsOf(g, flag, otherFlag); + } + return connectionJoin; } + public static void activateMappingForParentDiagramsOf(WriteGraph graph, Resource... elements) throws DatabaseException { + IActivationManager manager = graph.getService(IActivationManager.class); + Set diagrams = new HashSet<>(elements.length); + for (Resource e : elements) { + diagrams.addAll(OrderedSetUtils.getSubjects(graph, e)); + } + for (Resource diagram : diagrams) { + manager.activateOnce(graph, diagram); + } + } + public static void disconnectFlag(WriteGraph graph, Resource flag) throws DatabaseException { // Remove any :ConnectionJoin's this flag is joined by // if there's less than two flags joined by the join. @@ -531,5 +552,4 @@ public final class FlagUtil { return flags; } - -} +} \ No newline at end of file diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/flag/RouteGraphConnectionSplitter.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/flag/RouteGraphConnectionSplitter.java index 3f1076b5d..5c85a9944 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/flag/RouteGraphConnectionSplitter.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/flag/RouteGraphConnectionSplitter.java @@ -1,11 +1,10 @@ package org.simantics.diagram.flag; -import gnu.trove.map.hash.TObjectIntHashMap; - import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; @@ -24,9 +23,11 @@ import org.simantics.diagram.connection.RouteNode; import org.simantics.diagram.connection.RoutePoint; import org.simantics.diagram.connection.RouteTerminal; import org.simantics.diagram.connection.splitting.SplittedRouteGraph; +import org.simantics.diagram.connection.splitting.SplittedRouteGraph.PickResult; import org.simantics.diagram.content.ConnectionUtil; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.diagram.synchronization.graph.AddElement; +import org.simantics.diagram.synchronization.graph.BasicResources; import org.simantics.diagram.synchronization.graph.DiagramGraphUtil; import org.simantics.diagram.synchronization.graph.RouteGraphModification; import org.simantics.g2d.elementclass.FlagClass; @@ -34,6 +35,8 @@ import org.simantics.layer0.Layer0; import org.simantics.modeling.ModelingResources; import org.simantics.structural.stubs.StructuralResource2; +import gnu.trove.map.hash.TObjectIntHashMap; + /** * A class that handles splitting a route graph connection in two with diagram * local flags. @@ -87,34 +90,33 @@ public class RouteGraphConnectionSplitter { RouteGraphModification modis = new RouteGraphModification(ss, rg); TObjectIntHashMap idMap = modis.getIdMap(); + if (DEBUG) { + System.out.println("Split canvas position: " + splitCanvasPos); + rg.print(); + } + // Find the edge to disconnect in the graph. // Bisect the nearest route line. - RouteLine line = SplittedRouteGraph.findNearestLine(rg, splitCanvasPos); - if (DEBUG) - rg.print(); - if (line == null) + PickResult picked = SplittedRouteGraph.pickNearestLine(rg, splitCanvasPos.getX(), splitCanvasPos.getY()); + if (picked == null) return; + + RouteLine line = picked.nearestLine; + if (DEBUG) { + System.out.println("picked nearest line:"); line.print(System.out); for (RoutePoint rp : line.getPoints()) System.out.println("RP: " + rp.getX() + ", " + rp.getY()); } // Get exact intersection point on the line - double isectX = splitCanvasPos.getX(); - double isectY = splitCanvasPos.getY(); - SplittedRouteGraph srg; - if (line.isHorizontal()) { - isectY = line.getPosition(); - srg = rg.splitGraph(line, isectX); - } - else { - isectX = line.getPosition(); - srg = rg.splitGraph(line, isectY); - } + double isectX = picked.intersectionPoint.getX(); + double isectY = picked.intersectionPoint.getY(); + SplittedRouteGraph srg = rg.splitGraph(line, line.isHorizontal() ? isectX : isectY); if (DEBUG) System.out.println(srg); - + // Disconnect if(rg.isSimpleConnection()) { RouteNode na = srg.terminals1.iterator().next(); @@ -141,44 +143,106 @@ public class RouteGraphConnectionSplitter { idMap.get(srg.splitLine) )); } - - ArrayList interfaceNodes1Resources = new ArrayList(srg.interfaceNodes1.size()); - for(RouteNode n : srg.interfaceNodes1) - interfaceNodes1Resources.add(ss.getResource((Long)n.getData())); - ArrayList interfaceNodes2Resources = new ArrayList(srg.interfaceNodes2.size()); - for(RouteNode n : srg.interfaceNodes2) - interfaceNodes2Resources.add(ss.getResource((Long)n.getData())); - - ArrayList lines2Resources = new ArrayList(srg.lines2.size()); - for(RouteLine n : srg.lines2) - lines2Resources.add(ss.getResource((Long)n.getData())); - - ArrayList terminals1Resources = new ArrayList(srg.terminals1.size()); - for(RouteTerminal n : srg.terminals1) - terminals1Resources.add(ss.getResource((Long)n.getData())); - ArrayList terminals2Resources = new ArrayList(srg.terminals2.size()); - for(RouteTerminal n : srg.terminals2) - terminals2Resources.add(ss.getResource((Long)n.getData())); + ArrayList terminals1Resources = toResources(srg.terminals1); + ArrayList terminals2Resources = toResources(srg.terminals2); + + boolean mustFlip = analyzePartInputs(graph, terminals1Resources, terminals2Resources); + + ArrayList interfaceNodes1 = toResources(mustFlip ? srg.interfaceNodes2 : srg.interfaceNodes1); + ArrayList interfaceNodes2 = toResources(mustFlip ? srg.interfaceNodes1 : srg.interfaceNodes2); + + ArrayList lines2 = toResources(mustFlip ? srg.lines1 : srg.lines2); + ArrayList terminals1 = mustFlip ? terminals2Resources : terminals1Resources; + ArrayList terminals2 = mustFlip ? terminals1Resources : terminals2Resources; + doSplit(graph, connection, - interfaceNodes1Resources, - interfaceNodes2Resources, - lines2Resources, - terminals1Resources, - terminals2Resources, + interfaceNodes1, + interfaceNodes2, + lines2, + terminals1, + terminals2, line.isHorizontal(), + mustFlip, isectX, isectY); modis.addModi(new RouteGraphModification.Split( - modis.toIds(interfaceNodes1Resources), - modis.toIds(interfaceNodes2Resources), - modis.toIds(lines2Resources), - modis.toIds(terminals1Resources), - modis.toIds(terminals2Resources), + modis.toIds(interfaceNodes1), + modis.toIds(interfaceNodes2), + modis.toIds(lines2), + modis.toIds(terminals1), + modis.toIds(terminals2), line.isHorizontal(), + mustFlip, isectX, isectY )); - } - + + private ArrayList toResources(Collection nodes) throws DatabaseException { + ArrayList result = new ArrayList<>(nodes.size()); + for (RouteNode n : nodes) + result.add(ss.getResource((Long)n.getData())); + return result; + } + + /** + * @param graph + * @param terminals1 + * @param terminals2 + * @return true if inputs need to be flipped, i.e. if terminals2 + * contains the output terminals and terminals1 doesn't. + * @throws DatabaseException + */ + private boolean analyzePartInputs(ReadGraph graph, List terminals1, List terminals2) throws DatabaseException { + @SuppressWarnings("unused") + int inputs1 = 0, outputs1 = 0; + for(Resource connector : terminals1) { + if(graph.hasStatement(connector, DIA.IsHeadConnectorOf)) + ++inputs1; + else + ++outputs1; + } + @SuppressWarnings("unused") + int inputs2 = 0, outputs2 = 0; + for(Resource connector : terminals2) { + if(graph.hasStatement(connector, DIA.IsHeadConnectorOf)) + ++inputs2; + else + ++outputs2; + } + + boolean mustFlip = outputs1 == 0; + + if (DEBUG) { + System.out.println("inputs1: " + inputs1); + System.out.println("outputs1: " + outputs1); + System.out.println("inputs2: " + inputs2); + System.out.println("outputs2: " + outputs2); + System.out.println("=> type1: " + (mustFlip ? FlagClass.Type.In : FlagClass.Type.Out)); + System.out.println("=> type2: " + (mustFlip ? FlagClass.Type.Out : FlagClass.Type.In)); + System.out.println("=> must flip route graph parts to split: " + mustFlip); + } + + return mustFlip; + } + + private static String routeNodeDebugInfo(ReadGraph graph, Resource c) throws DatabaseException { + BasicResources BR = BasicResources.getInstance(graph); + String ctr = NameUtils.getSafeName(graph, c, true); + for (Resource e : graph.getObjects(c, BR.STR.Connects)) { + ctr += " --> " + NameUtils.getSafeName(graph, e); + } + for (Resource e : graph.getObjects(c, BR.DIA.AreConnected)) { + ctr += " <-> " + NameUtils.getSafeName(graph, e); + } + return ctr; + } + + /** + * Internal routine that is only public because + * {@link RouteGraphModification#runUpdates(WriteGraph)} needs to invoke it. + * + * Assumes that #1 parameters will stay with the existing connection and #2 + * parameters will go to the newly created connection. + */ public void doSplit(WriteGraph graph, Resource connection, ArrayList interfaceNodes1Resources, @@ -186,22 +250,28 @@ public class RouteGraphConnectionSplitter { ArrayList lines2Resources, ArrayList terminals1Resources, ArrayList terminals2Resources, - boolean isHorizontal, + boolean isHorizontal, + boolean invertFlagRotation, double isectX, double isectY) throws DatabaseException { + // 1 = output, 2 = input + FlagClass.Type + type1 = FlagClass.Type.Out, + type2 = FlagClass.Type.In; + if (DEBUG) { System.out.println("doSplit:"); System.out.println(NameUtils.getSafeName(graph, connection, true)); for (Resource i : interfaceNodes1Resources) - System.out.println("i1: " + NameUtils.getSafeName(graph, i, true)); + System.out.println("i1: " + routeNodeDebugInfo(graph, i)); for (Resource i : interfaceNodes2Resources) - System.out.println("i2: " + NameUtils.getSafeName(graph, i, true)); + System.out.println("i2: " + routeNodeDebugInfo(graph, i)); for (Resource l : lines2Resources) - System.out.println("l2r: " + NameUtils.getSafeName(graph, l, true)); + System.out.println("l2r: " + routeNodeDebugInfo(graph, l)); for (Resource t : terminals1Resources) - System.out.println("t1: " + NameUtils.getSafeName(graph, t, true)); + System.out.println("t1: " + routeNodeDebugInfo(graph, t)); for (Resource t : terminals2Resources) - System.out.println("t2: " + NameUtils.getSafeName(graph, t, true)); + System.out.println("t2: " + routeNodeDebugInfo(graph, t)); System.out.println("is horizontal: " + isHorizontal); System.out.println("@(x,y): " + isectX + ", " + isectY); } @@ -209,15 +279,39 @@ public class RouteGraphConnectionSplitter { ConnectionUtil cu = new ConnectionUtil(graph); Resource diagram = OrderedSetUtils.getSingleOwnerList(graph, connection, DIA.Diagram); - Resource connectionType = graph.getSingleType(connection, DIA.Connection); + Resource diagramConnectionType = graph.getSingleType(connection, DIA.Connection); Resource hasConnectionType = graph.getPossibleObject(connection, STR.HasConnectionType); - Resource newConnection = cu.newConnection(diagram, connectionType); + Resource newConnection = cu.newConnection(diagram, diagramConnectionType); if (hasConnectionType != null) graph.claim(newConnection, STR.HasConnectionType, null, hasConnectionType); // Give running name to connection increment the counter attached to the diagram. AddElement.claimFreshElementName(graph, diagram, newConnection); + String commonLabel = DiagramFlagPreferences + .getActiveFlagLabelingScheme(graph) + .generateLabel(graph, diagram); + + Point2D pos1, pos2; + double theta; + double flagDist = 3.0; + if(isHorizontal) { + theta = 0.0; + pos1 = new Point2D.Double(isectX-flagDist, isectY); + pos2 = new Point2D.Double(isectX+flagDist, isectY); + } else { + theta = Math.PI*0.5; + pos1 = new Point2D.Double(isectX, isectY-flagDist); + pos2 = new Point2D.Double(isectX, isectY+flagDist); + } + + if (invertFlagRotation) { + theta += Math.PI; + Point2D p = pos1; + pos1 = pos2; + pos2 = p; + } + // WORKAROUND for mapping problems: // If any terminal of the split connection contains a flag, make sure their STR.Joins relations are all removed // to give mapping a chance to fix them properly. @@ -237,97 +331,31 @@ public class RouteGraphConnectionSplitter { graph.claim(rn, predicate, newConnection); } - // 1 = output, 2 = input - FlagClass.Type type1, type2; - - FlagLabelingScheme scheme = DiagramFlagPreferences.getActiveFlagLabelingScheme(graph); - String commonLabel = scheme.generateLabel(graph, diagram); - // Create flags and connect both disconnected ends to them. - Point2D pos1, pos2; - double theta; - double flagDist = 3.0; - if(isHorizontal) { - theta = 0.0; - pos1 = new Point2D.Double(isectX-flagDist, isectY); - pos2 = new Point2D.Double(isectX+flagDist, isectY); - } - else { - theta = Math.PI*0.5; - pos1 = new Point2D.Double(isectX, isectY-flagDist); - pos2 = new Point2D.Double(isectX, isectY+flagDist); - } - - // Chooses flag directions - { - @SuppressWarnings("unused") - int inputs1 = 0, outputs1 = 0; - for(Resource connector : terminals1Resources) { - if(graph.hasStatement(connector, DIA.IsHeadConnectorOf)) - ++inputs1; - else - ++outputs1; - } - @SuppressWarnings("unused") - int inputs2 = 0, outputs2 = 0; - for(Resource connector : terminals2Resources) { - if(graph.hasStatement(connector, DIA.IsHeadConnectorOf)) - ++inputs2; - else - ++outputs2; - } - - if(outputs1 == 0) { - type1 = FlagClass.Type.In; - type2 = FlagClass.Type.Out; - theta += Math.PI; - } - else { - type1 = FlagClass.Type.Out; - type2 = FlagClass.Type.In; - } - if (DEBUG) { - System.out.println("inputs1: " + inputs1); - System.out.println("outputs1: " + outputs1); - System.out.println("=> type1: " + type1); - System.out.println("inputs2: " + inputs2); - System.out.println("outputs2: " + outputs2); - System.out.println("=> type2: " + type2); - } - } Resource flag1 = createFlag(graph, diagram, getFlagTransform(pos1, theta), type1, commonLabel); Resource flag2 = createFlag(graph, diagram, getFlagTransform(pos2, theta), type2, commonLabel); + if (DEBUG) { + System.out.println("LABEL FOR NEW FLAGS: " + commonLabel); System.out.println("FLAG1: " + NameUtils.getSafeName(graph, flag1, true)); System.out.println("FLAG2: " + NameUtils.getSafeName(graph, flag2, true)); } -// System.out.println("conn1: " + NameUtils.getSafeLabel(graph, type1 == FlagClass.Type.In ? DIA.HasPlainConnector : DIA.HasArrowConnector)); -// System.out.println("conn2: " + NameUtils.getSafeLabel(graph, type2 == FlagClass.Type.In ? DIA.HasPlainConnector : DIA.HasArrowConnector)); - Resource flagConnector1 = cu.newConnector(connection, - type1 == FlagClass.Type.In ? DIA.HasPlainConnector : DIA.HasArrowConnector); - Resource flagConnector2 = cu.newConnector(newConnection, - type2 == FlagClass.Type.In ? DIA.HasPlainConnector : DIA.HasArrowConnector); + Resource flagConnector1 = cu.newConnector(connection, DIA.HasArrowConnector); + Resource flagConnector2 = cu.newConnector(newConnection, DIA.HasPlainConnector); graph.claim(flag1, DIA.Flag_ConnectionPoint, flagConnector1); graph.claim(flag2, DIA.Flag_ConnectionPoint, flagConnector2); double position = isHorizontal ? isectY : isectX; - connectFlag(graph, isHorizontal, position, connection, flagConnector1, - interfaceNodes1Resources); - connectFlag(graph, isHorizontal, position, newConnection, flagConnector2, - interfaceNodes2Resources); - - FlagUtil.join(graph, flag1, flag2); - - // Move mapping relations to new connection if necessary - if(type1 == FlagClass.Type.In) { - moveStatements(graph, connection, newConnection, MOD.ElementToComponent); - moveStatements(graph, connection, newConnection, MOD.DiagramConnectionToConnection); - moveStatements(graph, connection, newConnection, MOD.DiagramConnectionToConnectionSpecial); - FlagUtil.fixBindsStatements(graph, graph.getPossibleObject(newConnection, MOD.DiagramConnectionToConnection)); - } - else - FlagUtil.fixBindsStatements(graph, graph.getPossibleObject(connection, MOD.DiagramConnectionToConnection)); + connectFlag(graph, isHorizontal, position, connection, flagConnector1, interfaceNodes1Resources); + connectFlag(graph, isHorizontal, position, newConnection, flagConnector2, interfaceNodes2Resources); + + // Join the flags without activatingn diagram mapping at this point + FlagUtil.join(graph, flag1, flag2, false); + FlagUtil.fixBindsStatements(graph, graph.getPossibleObject(connection, MOD.DiagramConnectionToConnection)); + + // Finally ensure that all the diagrams related to the operation are mapped properly in one go + FlagUtil.activateMappingForParentDiagramsOf(graph, flag1, flag2); } /** @@ -370,15 +398,6 @@ public class RouteGraphConnectionSplitter { } } - private static void moveStatements(WriteGraph graph, Resource from, Resource to, Resource relation) throws DatabaseException { - if(from.equals(to)) - return; - for(Statement stat : graph.getStatements(from, relation)) - if(stat.getSubject().equals(from)) - graph.claim(to, stat.getPredicate(), stat.getObject()); - graph.deny(from, relation); - } - private void connectFlag(WriteGraph graph, boolean isHorizontal, double position, Resource connection, Resource flagConnector, Collection interfaceNodes) throws DatabaseException { if(interfaceNodes.size() > 1) { @@ -421,6 +440,7 @@ public class RouteGraphConnectionSplitter { } public static void splitConnection(WriteGraph graph, Resource connection, double x, double y) throws DatabaseException { + // TODO: provide a proper runtimeDiagram parameter to load to support also connections attached to flags attached to diagram template flag tables RouteGraph rg = RouteGraphUtils.load(graph, null, connection); new RouteGraphConnectionSplitter(graph).split(graph, connection, rg, new Point2D.Double(x, y)); } diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/function/All.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/function/All.java index 6cd4c542f..5bb793f7d 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/function/All.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/function/All.java @@ -95,6 +95,8 @@ public class All { Resource flag = context.element; Resource runtimeDiagram = context.runtime; + if (runtimeDiagram == null) + return flagTransformImpl(graph, converter, context); Resource diagram = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasConfiguration); if (diagram == null) diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/CopyPasteHandler.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/CopyPasteHandler.java index 52217c3cf..de10603d3 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/CopyPasteHandler.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/CopyPasteHandler.java @@ -44,7 +44,6 @@ import org.simantics.db.layer0.util.SimanticsKeys; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.db.request.Read; -import org.simantics.diagram.Logger; import org.simantics.diagram.content.Change; import org.simantics.diagram.content.ConnectionUtil; import org.simantics.diagram.content.DiagramContentChanges; @@ -114,6 +113,8 @@ import org.simantics.utils.threads.SWTThread; import org.simantics.utils.threads.ThreadUtils; import org.simantics.utils.ui.ErrorLogger; import org.simantics.utils.ui.SWTUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * CopyPasteHandler is a canvas handler for Commands.CUT, Commands.COPY and @@ -141,6 +142,8 @@ import org.simantics.utils.ui.SWTUtils; */ public class CopyPasteHandler extends AbstractDiagramParticipant { + private static final Logger LOGGER = LoggerFactory.getLogger(CopyPasteHandler.class); + public static final Key KEY_CUT_SELECTION_FRAME_COLOR = new KeyOf(Color.class, "CUT_SELECTION_FRAME_COLOR"); public static final Key KEY_CUT_SELECTION_CONTENT_COLOR = new KeyOf(Color.class, "CUT_SELECTION_CONTENT_COLOR"); public static final Key KEY_COPIED_SELECTION_FRAME_COLOR = new KeyOf(Color.class, "COPY_SELECTION_FRAME_COLOR"); @@ -1294,7 +1297,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant { }); } } catch (DatabaseException e1) { - Logger.defaultLogError(e1); + LOGGER.error("Monitor paste failed", e1); } } return true; diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/e4/CopyPasteHandler.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/e4/CopyPasteHandler.java index 761494127..7f709c709 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/e4/CopyPasteHandler.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/e4/CopyPasteHandler.java @@ -44,7 +44,6 @@ import org.simantics.db.layer0.util.SimanticsKeys; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.db.request.Read; -import org.simantics.diagram.Logger; import org.simantics.diagram.content.Change; import org.simantics.diagram.content.ConnectionUtil; import org.simantics.diagram.content.DiagramContentChanges; @@ -125,6 +124,8 @@ import org.simantics.utils.threads.SWTThread; import org.simantics.utils.threads.ThreadUtils; import org.simantics.utils.ui.ErrorLogger; import org.simantics.utils.ui.SWTUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * CopyPasteHandler is a canvas handler for Commands.CUT, Commands.COPY and @@ -152,6 +153,8 @@ import org.simantics.utils.ui.SWTUtils; */ public class CopyPasteHandler extends AbstractDiagramParticipant { + private static final Logger LOGGER = LoggerFactory.getLogger(CopyPasteHandler.class); + public static final Key KEY_CUT_SELECTION_FRAME_COLOR = new KeyOf(Color.class, "CUT_SELECTION_FRAME_COLOR"); public static final Key KEY_CUT_SELECTION_CONTENT_COLOR = new KeyOf(Color.class, "CUT_SELECTION_CONTENT_COLOR"); public static final Key KEY_COPIED_SELECTION_FRAME_COLOR = new KeyOf(Color.class, "COPY_SELECTION_FRAME_COLOR"); @@ -1291,7 +1294,7 @@ public class CopyPasteHandler extends AbstractDiagramParticipant { }); } } catch (DatabaseException e1) { - Logger.defaultLogError(e1); + LOGGER.error("Monitor paste failed", e1); } } return true; diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/PopulateSelectionDropParticipant.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/PopulateSelectionDropParticipant.java index 3e1140a07..0731bd90d 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/PopulateSelectionDropParticipant.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/PopulateSelectionDropParticipant.java @@ -24,10 +24,8 @@ import java.util.List; import org.eclipse.jface.viewers.IStructuredSelection; import org.simantics.db.Session; import org.simantics.db.exception.DatabaseException; -import org.simantics.diagram.Logger; import org.simantics.diagram.adapter.GraphToDiagramSynchronizer; import org.simantics.g2d.diagram.DiagramHints; -import org.simantics.g2d.diagram.DiagramMutator; import org.simantics.g2d.diagram.DiagramUtils; import org.simantics.g2d.diagram.IDiagram; import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant; @@ -42,11 +40,14 @@ import org.simantics.g2d.element.IElement; import org.simantics.scenegraph.g2d.snap.ISnapAdvisor; import org.simantics.ui.dnd.LocalObjectTransfer; import org.simantics.ui.dnd.LocalObjectTransferable; -import org.simantics.utils.datastructures.Callback; import org.simantics.utils.logging.TimeLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; abstract public class PopulateSelectionDropParticipant extends AbstractDiagramParticipant implements IDropTargetParticipant { + private static final Logger LOGGER = LoggerFactory.getLogger(PopulateSelectionDropParticipant.class); + public abstract List getElements(Session session, IStructuredSelection selection) throws DatabaseException; protected GraphToDiagramSynchronizer synchronizer; @@ -96,12 +97,8 @@ abstract public class PopulateSelectionDropParticipant extends AbstractDiagramPa } - } catch (UnsupportedFlavorException e) { - Logger.defaultLogError(e); - } catch (IOException e) { - Logger.defaultLogError(e); - } catch (DatabaseException e) { - Logger.defaultLogError(e); + } catch (DatabaseException | IOException | UnsupportedFlavorException e) { + LOGGER.error("Unexpected failure", e); } } diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/symbollibrary/ui/SymbolLibraryComposite.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/symbollibrary/ui/SymbolLibraryComposite.java index af58be479..31c091fd4 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/symbollibrary/ui/SymbolLibraryComposite.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/symbollibrary/ui/SymbolLibraryComposite.java @@ -88,7 +88,6 @@ import org.simantics.diagram.internal.Activator; import org.simantics.diagram.symbolcontribution.CompositeSymbolGroup; import org.simantics.diagram.symbolcontribution.IIdentifiedObject; import org.simantics.diagram.symbolcontribution.ISymbolProvider; -import org.simantics.diagram.symbolcontribution.IdentifiedObject; import org.simantics.diagram.symbolcontribution.SymbolProviderFactory; import org.simantics.diagram.symbollibrary.IModifiableSymbolGroup; import org.simantics.diagram.symbollibrary.ISymbolGroup; @@ -1118,24 +1117,22 @@ public class SymbolLibraryComposite extends Composite { json.append(" \"res\" : ["); int pos = 0; for(int i=0;i 0) json.append(","); - Object r = res[i]; - if(r instanceof IdentifiedObject) { - Object id = ((IdentifiedObject) r).getId(); - if(id instanceof IAdaptable) { - Object resource = ((IAdaptable) id).getAdapter(Resource.class); - if(resource != null) { - long rid = ((Resource)resource).getResourceId(); - json.append(Long.toString(rid)); - pos++; - } - } - } + if(pos > 0) json.append(","); + Object r = res[i]; + if(r instanceof IAdaptable) { + Resource resource = ((IAdaptable) r).getAdapter(Resource.class); + if(resource != null) { + long rid = resource.getResourceId(); + json.append(Long.toString(rid)); + pos++; + } + } } json.append("] }"); - StringSelection text = new StringSelection(json.toString()); - PlaintextTransfer plainText = new PlaintextTransfer(json.toString()); + String jsonText = json.toString(); + StringSelection text = new StringSelection(jsonText); + PlaintextTransfer plainText = new PlaintextTransfer(jsonText); return new MultiTransferable(local, text, plainText); diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/CopyAdvisorUtil.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/CopyAdvisorUtil.java index ab28463e8..bbf9a8e5b 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/CopyAdvisorUtil.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/CopyAdvisorUtil.java @@ -11,8 +11,6 @@ *******************************************************************************/ package org.simantics.diagram.synchronization.graph; -import gnu.trove.map.hash.THashMap; - import java.util.Map; import java.util.Set; import java.util.function.BiFunction; @@ -46,6 +44,10 @@ import org.simantics.diagram.synchronization.SynchronizationHints; import org.simantics.graph.db.TransferableGraphs; import org.simantics.graph.representation.TransferableGraph1; import org.simantics.layer0.Layer0; +import org.simantics.utils.datastructures.BinaryFunction; + +import gnu.trove.map.hash.THashMap; +import gnu.trove.set.hash.THashSet; /** * This class contains utility methods for the basic cut/copy operations @@ -82,6 +84,15 @@ public class CopyAdvisorUtil { public static final boolean DEBUG_COPY = DebugPolicy.DEBUG_COPY_PASTE; + private static class Statement4 { + public final Statement stm; + public final Resource inverse; + public Statement4(Statement stm, Resource inverse) { + this.stm = stm; + this.inverse = inverse; + } + } + /** * @param context a synchronization context instance, such as * {@link GraphToDiagramSynchronizer} @@ -364,8 +375,10 @@ public class CopyAdvisorUtil { * @throws DatabaseException */ public static Resource copy2(WriteGraph graph, Resource source, - BiFunction advisor) throws DatabaseException { - return copy2(graph, source, 0, advisor, new THashMap()); + BiFunction advisor) + throws DatabaseException + { + return copy2(graph, source, advisor, new THashMap<>()); } /** @@ -380,13 +393,52 @@ public class CopyAdvisorUtil { * @throws DatabaseException */ public static Resource copy2(WriteGraph graph, Resource source, - BiFunction advisor, Map copyMap) - throws DatabaseException { - return copy2(graph, source, 0, advisor, copyMap); + BiFunction advisor, + Map copyMap) + throws DatabaseException + { + Set pendingStatements = new THashSet<>(); + Resource result = copy2(graph, source, 0, advisor, copyMap, pendingStatements); + postProcessStatements(graph, copyMap, pendingStatements); + return result; + } + + /** + * Post-process pending statement + * + * Rule: If both the subject and object of a pending source statement have + * been copied, then the pending statement should also be copied. + */ + private static void postProcessStatements( + WriteGraph graph, + Map copyMap, + Set pendingStatements) + throws DatabaseException + { + if (pendingStatements.isEmpty()) + return; + + if (DEBUG_COPY) + System.out.println("post processing " + pendingStatements.size() + " pending statements"); + for (Statement4 srcStm : pendingStatements) { + // At this point, it is certain that srcStm subject has been copied + // but test it anyway. + Resource subjectCopy = (Resource) copyMap.get(srcStm.stm.getSubject()); + Resource objectCopy = (Resource) copyMap.get(srcStm.stm.getObject()); + if (subjectCopy == null || objectCopy == null) { + if (DEBUG_COPY) + System.out.println("skipping pending statement: " + NameUtils.toString(graph, srcStm.stm)); + continue; + } + if (DEBUG_COPY) + System.out.println("copying pending statement: " + NameUtils.toString(graph, srcStm.stm)); + graph.claim(subjectCopy, srcStm.stm.getPredicate(), srcStm.inverse, objectCopy); + } } private static Resource copy2(final WriteGraph graph, final Resource source, final int level, - BiFunction advisor, Map copyMap) + BiFunction advisor, Map copyMap, + Set pendingSourceStatements) throws DatabaseException { if (DEBUG_COPY) System.out.println("[" + level + "] CopyAdvisorUtil.copy(" + NameUtils.getSafeName(graph, source) + ", advisor=" + advisor + ")"); @@ -497,12 +549,18 @@ public class CopyAdvisorUtil { if (DEBUG_COPY) System.out.println("[" + level + "]\t\tcopy whole object"); - Resource clone = copy2(graph, obj, level + 1, advisor, copyMap); + Resource clone = copy2(graph, obj, level + 1, advisor, copyMap, pendingSourceStatements); graph.claim(copy, relation, inverse, clone); } } else { - if (DEBUG_COPY) - System.out.println("[" + level + "]\t\tskipping statement"); + if (graph.isSubrelationOf(relation, L0.IsRelatedTo)) { + if (DEBUG_COPY) + System.out.println("[" + level + "]\t\tmarking statement as pending for post-processing"); + pendingSourceStatements.add(new Statement4(stm, inverse)); + } else { + if (DEBUG_COPY) + System.out.println("[" + level + "]\t\tskipping weak statement"); + } } } } diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/RouteGraphModification.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/RouteGraphModification.java index a15b99bc4..41f4c00e6 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/RouteGraphModification.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/RouteGraphModification.java @@ -162,12 +162,14 @@ public class RouteGraphModification { int[] lines2; int[] terminals1; int[] terminals2; - boolean isHorizontal; + boolean isHorizontal; + boolean invertFlagRotation; double isectX; double isectY; public Split(int[] interface1, int[] interface2, int[] lines2, int[] terminals1, int[] terminals2, boolean isHorizontal, + boolean invertFlagRotation, double isectX, double isectY) { this.interface1 = interface1; this.interface2 = interface2; @@ -175,6 +177,7 @@ public class RouteGraphModification { this.terminals1 = terminals1; this.terminals2 = terminals2; this.isHorizontal = isHorizontal; + this.invertFlagRotation = invertFlagRotation; this.isectX = isectX; this.isectY = isectY; } @@ -188,6 +191,7 @@ public class RouteGraphModification { this.terminals1 = readInts(it); this.terminals2 = readInts(it); this.isHorizontal = Boolean.parseBoolean(it.next()); + this.invertFlagRotation = Boolean.parseBoolean(it.next()); this.isectX = Double.parseDouble(it.next()); this.isectY = Double.parseDouble(it.next()); } @@ -208,6 +212,8 @@ public class RouteGraphModification { b.append("$"); b.append(isHorizontal); b.append("$"); + b.append(invertFlagRotation); + b.append("$"); b.append(isectX); b.append("$"); b.append(isectY); @@ -531,6 +537,7 @@ public class RouteGraphModification { toResources(modi.terminals1), toResources(modi.terminals2), modi.isHorizontal, + modi.invertFlagRotation, modi.isectX, modi.isectY ); diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/DocumentRequest.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/DocumentRequest.java index 8acc2f0d1..5b76cd344 100644 --- a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/DocumentRequest.java +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/DocumentRequest.java @@ -1,6 +1,7 @@ package org.simantics.document.server.request; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; @@ -10,7 +11,7 @@ import java.util.Set; import org.simantics.db.AsyncReadGraph; import org.simantics.db.ReadGraph; import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; -import org.simantics.db.common.request.AsyncReadRequest; +import org.simantics.db.common.request.UnaryAsyncRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.VariableRead; import org.simantics.db.layer0.variable.Variable; @@ -28,49 +29,55 @@ public class DocumentRequest extends VariableRead> { super(var); } - @Override - public List perform(ReadGraph graph) throws DatabaseException { - - long s = System.nanoTime(); - - Set nodes = graph.syncRequest(new NodesRequest(variable), TransientCacheAsyncListener.>instance()); - HashSet rs = new HashSet(); // result - if(nodes.isEmpty()) { - return Collections.emptyList(); - } + static class CollectNodesRequest extends UnaryAsyncRead, Collection> { - if(PROFILE) { - long dura = System.nanoTime()-s; - System.err.println("DocumentRequest1 " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph)); + public CollectNodesRequest(Collection nodes) { + super(nodes); } - graph.syncRequest(new AsyncReadRequest() { + @Override + public void perform(AsyncReadGraph graph, AsyncProcedure> procedure) { + HashSet rs = new HashSet(); // result - @Override - public void run(AsyncReadGraph graph) throws DatabaseException { + for(Variable node : parameter) { + graph.asyncRequest(new NodeRequest(node), new AsyncProcedure () { - for(Variable node : nodes) { - graph.asyncRequest(new NodeRequest(node), new AsyncProcedure () { - - @Override - public void execute(AsyncReadGraph graph, JSONObject result) { - synchronized (rs) { - rs.add(result); - } + @Override + public void execute(AsyncReadGraph graph, JSONObject result) { + synchronized(rs) { + rs.add(result); } + } - @Override - public void exception(AsyncReadGraph graph, Throwable throwable) { - } + @Override + public void exception(AsyncReadGraph graph, Throwable throwable) { + } + + }); - }); - - } - } - - }); + procedure.execute(graph, rs); + + } + + } + + @Override + public List perform(ReadGraph graph) throws DatabaseException { + + long s = System.nanoTime(); + + Set nodes = graph.syncRequest(new NodesRequest(variable), TransientCacheAsyncListener.>instance()); + if(nodes.isEmpty()) { + return Collections.emptyList(); + } + + if(PROFILE) { + long dura = System.nanoTime()-s; + System.err.println("DocumentRequest1 " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph)); + } + Collection rs = graph.syncRequest(new CollectNodesRequest(nodes)); if(PROFILE) { long dura = System.nanoTime()-s; diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/HandleEventRequest.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/HandleEventRequest.java index 606b361b6..4c611a9aa 100644 --- a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/HandleEventRequest.java +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/HandleEventRequest.java @@ -1,19 +1,17 @@ package org.simantics.document.server.request; import org.simantics.db.ReadGraph; +import org.simantics.db.common.request.UnaryRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; -import org.simantics.db.request.Read; import org.simantics.document.server.handler.AbstractEventHandler; import org.simantics.structural.stubs.StructuralResource2; -public class HandleEventRequest implements Read { - - final String id; +public class HandleEventRequest extends UnaryRead { public HandleEventRequest(String id) { - this.id = id; + super(id); } @Override @@ -21,7 +19,7 @@ public class HandleEventRequest implements Read { StructuralResource2.getInstance(graph); - Variable variable = Variables.getPossibleVariable(graph, id); + Variable variable = Variables.getPossibleVariable(graph, parameter); if(variable == null) return null; // System.err.println("EVENT " + variable.getURI(graph)); @@ -29,7 +27,7 @@ public class HandleEventRequest implements Read { if(handler instanceof AbstractEventHandler) return (AbstractEventHandler) handler; else - throw new DatabaseException("Handler for " + id + " is not instance of AbstractEventHandler (it is instance of " + (handler != null ? handler.getClass() : null) + ")"); + throw new DatabaseException("Handler for " + parameter + " is not instance of AbstractEventHandler (it is instance of " + (handler != null ? handler.getClass() : null) + ")"); } } \ No newline at end of file diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/NodesRequest.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/NodesRequest.java index 99526368e..133264e29 100644 --- a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/NodesRequest.java +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/NodesRequest.java @@ -2,11 +2,12 @@ package org.simantics.document.server.request; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Set; import org.simantics.db.AsyncReadGraph; import org.simantics.db.ReadGraph; -import org.simantics.db.common.request.AsyncReadRequest; +import org.simantics.db.common.request.UnaryAsyncRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.VariableChildren; import org.simantics.db.layer0.request.VariableRead; @@ -16,52 +17,57 @@ import org.simantics.structural.stubs.StructuralResource2; import org.simantics.utils.threads.logger.ITask; import org.simantics.utils.threads.logger.ThreadLogger; -import gnu.trove.set.hash.THashSet; - public class NodesRequest extends VariableRead> { public NodesRequest(Variable var) { super(var); } - @Override - public Set perform(ReadGraph graph) throws DatabaseException { + static class CollectNodesRequest2 extends UnaryAsyncRead, Set> { - ITask task = DocumentRequest.PROFILE ? ThreadLogger.task(this) : null; + public CollectNodesRequest2(Collection nodes) { + super(nodes); + } - StructuralResource2.getInstance(graph); - if(variable == null) - return Collections.emptySet(); + @Override + public void perform(AsyncReadGraph graph, AsyncProcedure> procedure) { + HashSet rs = new HashSet(); // result - Set nodes = new THashSet(); + for(Variable node : parameter) { + graph.asyncRequest(new NodesRequest2(node), new AsyncProcedure> () { - Collection children = graph.syncRequest(new VariableChildren(variable)); + @Override + public void execute(AsyncReadGraph graph, Set result) { + synchronized(rs) { + rs.addAll(result); + } + } - graph.syncRequest(new AsyncReadRequest() { + @Override + public void exception(AsyncReadGraph graph, Throwable throwable) { + } - @Override - public void run(AsyncReadGraph graph) throws DatabaseException { + }); - for(Variable child : children) { - graph.asyncRequest(new NodesRequest2(child), new AsyncProcedure>() { + } + procedure.execute(graph, rs); - @Override - public void execute(AsyncReadGraph graph, Set result) { - synchronized(nodes) { - nodes.addAll(result); - } - } + } - @Override - public void exception(AsyncReadGraph graph, Throwable throwable) { - } - - }); - } + } - } + @Override + public Set perform(ReadGraph graph) throws DatabaseException { + + ITask task = DocumentRequest.PROFILE ? ThreadLogger.task(this) : null; + + StructuralResource2.getInstance(graph); + if(variable == null) + return Collections.emptySet(); + + Collection children = graph.syncRequest(new VariableChildren(variable)); - }); + Set nodes = graph.syncRequest(new CollectNodesRequest2(children)); if(DocumentRequest.PROFILE) task.finish(); diff --git a/bundles/org.simantics.fileimport/META-INF/MANIFEST.MF b/bundles/org.simantics.fileimport/META-INF/MANIFEST.MF index 57c7e90ba..7adcb430e 100644 --- a/bundles/org.simantics.fileimport/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.fileimport/META-INF/MANIFEST.MF @@ -5,7 +5,6 @@ Bundle-SymbolicName: org.simantics.fileimport;singleton:=true Bundle-Version: 1.0.0.qualifier Bundle-Activator: org.simantics.fileimport.Activator Require-Bundle: org.eclipse.core.runtime, - org.apache.log4j, org.simantics.db, org.simantics, org.simantics.graphfile;bundle-version="0.1.0", diff --git a/bundles/org.simantics.g2d.ontology/graph/G2D.pgraph b/bundles/org.simantics.g2d.ontology/graph/G2D.pgraph index 4c44b6152..269f6a4fb 100644 --- a/bundles/org.simantics.g2d.ontology/graph/G2D.pgraph +++ b/bundles/org.simantics.g2d.ontology/graph/G2D.pgraph @@ -212,7 +212,9 @@ G2D.HasVerticalAlignment G2D.Color diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/gallery/GalleryViewer.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/gallery/GalleryViewer.java index 5bbe9f26e..d09ecf4a6 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/gallery/GalleryViewer.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/gallery/GalleryViewer.java @@ -631,8 +631,10 @@ public class GalleryViewer extends ContentViewer { ctx.getThreadAccess().asyncExec(() -> { //System.out.println(Thread.currentThread() + ": update scene graph(" + el + ")"); // Update scene graph and repaint. - el.getElementClass().getSingleItem(GalleryItemSGNode.class).update(el); - ctx.getContentContext().setDirty(); + if (!ctx.isDisposed()) { + el.getElementClass().getSingleItem(GalleryItemSGNode.class).update(el); + ctx.getContentContext().setDirty(); + } }); break; } diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/image/impl/ShapeImage.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/image/impl/ShapeImage.java index 77c65cb6e..90ceaa12a 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/image/impl/ShapeImage.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/image/impl/ShapeImage.java @@ -21,7 +21,7 @@ import java.util.EnumSet; import org.simantics.g2d.image.Image; import org.simantics.scenegraph.Node; import org.simantics.scenegraph.g2d.G2DParentNode; -import org.simantics.scenegraph.g2d.nodes.ShapeNode; +import org.simantics.scenegraph.g2d.nodes.ShapeNode2; /** * @author Tuukka Lehtonen @@ -31,7 +31,8 @@ public class ShapeImage extends AbstractImage implements Image { private static final EnumSet defaultFeats = VECTOR; Shape shape; - Paint paint; + Paint fillPaint; + Paint strokePaint; Stroke stroke; EnumSet feats; boolean scaleStroke = false; @@ -41,16 +42,20 @@ public class ShapeImage extends AbstractImage implements Image { } public ShapeImage(Shape shape, Paint fill, Stroke stroke, boolean scaleStroke) { - this(shape, fill, stroke, scaleStroke, defaultFeats); + this(shape, fill, stroke, fill, scaleStroke, defaultFeats); } public ShapeImage(Shape shape, Paint fill, Stroke stroke, EnumSet features) { - this(shape, fill, stroke, false, features); + this(shape, fill, stroke, fill, false, features); + } + public ShapeImage(Shape shape, Paint fill, Stroke stroke, Paint strokeColor, boolean scaleStroke) { + this(shape, fill, stroke, strokeColor, scaleStroke, defaultFeats); } - public ShapeImage(Shape shape, Paint fill, Stroke stroke, boolean scaleStroke, EnumSet features) { + public ShapeImage(Shape shape, Paint fill, Stroke stroke, Paint strokeColor, boolean scaleStroke, EnumSet features) { this.shape = shape; - this.paint = fill; + this.fillPaint = fill; + this.strokePaint = strokeColor; this.stroke = stroke; this.scaleStroke = scaleStroke; this.feats = features; @@ -73,11 +78,11 @@ public class ShapeImage extends AbstractImage implements Image { @Override public Node init(G2DParentNode parent) { - ShapeNode shapeNode = parent.getOrCreateNode("ShapeImage", ShapeNode.class); + ShapeNode2 shapeNode = parent.getOrCreateNode("ShapeImage", ShapeNode2.class); shapeNode.setShape(shape); shapeNode.setStroke(stroke); - shapeNode.setFill(paint != null); - shapeNode.setColor(paint != null ? paint : Color.BLACK); + shapeNode.setFillColor(fillPaint); + shapeNode.setStrokeColor(strokePaint != null ? strokePaint : Color.BLACK); shapeNode.setScaleStroke(scaleStroke); return shapeNode; } diff --git a/bundles/org.simantics.graph/src/org/simantics/graph/refactoring/FixExportedOntology.java b/bundles/org.simantics.graph/src/org/simantics/graph/refactoring/FixExportedOntology.java index 17aa3ed26..33291cdf1 100644 --- a/bundles/org.simantics.graph/src/org/simantics/graph/refactoring/FixExportedOntology.java +++ b/bundles/org.simantics.graph/src/org/simantics/graph/refactoring/FixExportedOntology.java @@ -41,8 +41,9 @@ public class FixExportedOntology { private static Path replaceExtension(Path p, String newExtension) { String newName = p.getFileName().toString(); - if (newName.contains(".")) - newName = newName.split("\\.")[0]; + int lastDot = newName.lastIndexOf('.'); + if (lastDot > -1) + newName = newName.substring(0, lastDot); return p.resolveSibling(newName + newExtension); } diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DiagramViewerSelectionProvider.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DiagramViewerSelectionProvider.java index b7ea5ac78..d9d14c37e 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DiagramViewerSelectionProvider.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DiagramViewerSelectionProvider.java @@ -17,7 +17,6 @@ import org.simantics.db.layer0.SelectionHints; import org.simantics.db.layer0.request.PossibleModel; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; -import org.simantics.diagram.Logger; import org.simantics.diagram.flag.FlagUtil; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.diagram.ui.DiagramModelHints; @@ -36,6 +35,8 @@ import org.simantics.ui.selection.WorkbenchSelectionContentType; import org.simantics.utils.DataContainer; import org.simantics.utils.threads.IThreadWorkQueue; import org.simantics.utils.ui.ErrorLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author Antti Villberg @@ -44,6 +45,8 @@ public class DiagramViewerSelectionProvider extends WorkbenchSelectionProvider { protected static class SelectionElement extends AdaptableHintContext { + private static final Logger LOGGER = LoggerFactory.getLogger(SelectionElement.class); + final public Resource runtime; final public Resource element; @@ -108,7 +111,7 @@ public class DiagramViewerSelectionProvider extends WorkbenchSelectionProvider { } }); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("WorkbenchSelectionElement.getContent failed for type AnyVariable", e); } } else if(contentType instanceof ParentVariable) { @@ -117,10 +120,7 @@ public class DiagramViewerSelectionProvider extends WorkbenchSelectionProvider { return (T) type.processor.sync(new ResourceRead2(runtime, element) { @Override public Variable perform(ReadGraph graph) throws DatabaseException { - DiagramResource DIA = DiagramResource.getInstance(graph); - ModelingResources MOD = ModelingResources.getInstance(graph); - Layer0 L0 = Layer0.getInstance(graph); String uri = graph.getPossibleRelatedValue(resource, DIA.RuntimeDiagram_HasVariable); if (uri == null) @@ -134,7 +134,7 @@ public class DiagramViewerSelectionProvider extends WorkbenchSelectionProvider { } }); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("WorkbenchSelectionElement.getContent failed for type ParentVariable", e); } } diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/e4/PopulateElementDropParticipant.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/e4/PopulateElementDropParticipant.java index ac9413064..4e7ac0ab8 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/e4/PopulateElementDropParticipant.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/e4/PopulateElementDropParticipant.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * Copyright (c) 2007, 2020 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 @@ -45,7 +45,6 @@ import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.IsLinkedTo; import org.simantics.db.layer0.util.Layer0Utils; import org.simantics.db.service.SerialisationSupport; -import org.simantics.diagram.Logger; import org.simantics.diagram.adapter.GraphToDiagramSynchronizer; import org.simantics.diagram.content.Change; import org.simantics.diagram.content.DiagramContentChanges; @@ -83,12 +82,16 @@ import org.simantics.ui.dnd.LocalObjectTransferable; import org.simantics.ui.selection.WorkbenchSelectionElement; import org.simantics.ui.workbench.e4.E4WorkbenchUtils; import org.simantics.utils.logging.TimeLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * This participant populates Elements from ElementClass-resources drops */ public class PopulateElementDropParticipant extends AbstractDiagramParticipant implements IDropTargetParticipant { + private static final Logger LOGGER = LoggerFactory.getLogger(PopulateElementDropParticipant.class); + @Dependency PickContext pickContext; @Dependency TransformUtil transformUtil; @@ -321,7 +324,7 @@ public class PopulateElementDropParticipant extends AbstractDiagramParticipant i }); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("symbolDropHandler invocation failed", e); } return; diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/modelBrowser/handlers/ContextualHelp.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/modelBrowser/handlers/ContextualHelp.java index 0d0ec7ce6..e7bfd35fa 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/modelBrowser/handlers/ContextualHelp.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/modelBrowser/handlers/ContextualHelp.java @@ -20,16 +20,13 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.handlers.HandlerUtil; import org.simantics.Simantics; -import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.UniqueRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.variable.Variable; -import org.simantics.modeling.ModelingResources; -import org.simantics.modeling.PropertyVariables; +import org.simantics.modeling.help.HelpContexts; import org.simantics.ui.selection.WorkbenchSelectionUtils; -import org.simantics.utils.ui.AdaptionUtils; import org.slf4j.LoggerFactory; public class ContextualHelp extends AbstractHandler { @@ -47,7 +44,7 @@ public class ContextualHelp extends AbstractHandler { return Simantics.getSession().syncRequest(new UniqueRead() { @Override public String perform(ReadGraph graph) throws DatabaseException { - return getPossibleId(graph, resource, variable, sel); + return HelpContexts.getPossibleId(graph, resource, variable, sel); } }); } catch (DatabaseException e) { @@ -64,34 +61,12 @@ public class ContextualHelp extends AbstractHandler { return null; } + /** + * @deprecated use {@link HelpContexts#getPossibleId(ReadGraph, Resource, Variable, Object)} instead + */ + @Deprecated public static String getPossibleId(ReadGraph graph, Resource resource, Variable variable, ISelection sel) throws DatabaseException { - ModelingResources MOD = ModelingResources.getInstance(graph); - if (resource != null) { - Resource component = graph.getPossibleObject(resource, MOD.ElementToComponent); - String id = component != null ? graph.getPossibleRelatedValue2(component, MOD.contextualHelpId, Bindings.STRING) : null; - if (id != null) - return id; - id = graph.getPossibleRelatedValue2(resource, MOD.contextualHelpId, Bindings.STRING); - if (id != null) - return id; - } - - if (variable != null) { - String id = variable.getPossiblePropertyValue(graph, MOD.contextualHelpId, Bindings.STRING); - if (id != null) - return id; - } - - // TODO: consider removing this block - if (sel != null) { - PropertyVariables vars = AdaptionUtils.adaptToSingle(sel, PropertyVariables.class); - Variable var = vars != null ? vars.getConfiguration() : null; - String id = var != null ? var.getPossiblePropertyValue(graph, MOD.contextualHelpId, Bindings.STRING) : null; - if (id != null) - return id; - } - - return null; + return HelpContexts.getPossibleId(graph, resource, variable, sel); } } diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFPainter.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFPainter.java index bec1e5408..0b7cd63e4 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFPainter.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFPainter.java @@ -89,7 +89,15 @@ public class PDFPainter { ThreadUtils.asyncExec(thread, () -> { try { - PDFBuilder chassis = new PDFBuilder(writer, mapper, pageSize, pageDesc, fitDiagramContentsToPageMargins || isSymbol); + boolean fitToContent = fitDiagramContentsToPageMargins || isSymbol; + if (!fitToContent) { + // Prevent PDF printing from drawing page borders if the + // print area is fitted directly to the page size. + // This avoids unwanted black half-visible edges. + ctx.getDefaultHintContext().setHint(Hints.KEY_DISPLAY_PAGE, false); + } + + PDFBuilder chassis = new PDFBuilder(writer, mapper, pageSize, pageDesc, fitToContent); chassis.paint(ctx, true); } catch (Throwable e) { exception[0] = new DatabaseException(e); diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java index 8f223a622..302e074fc 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java @@ -26,6 +26,7 @@ import org.simantics.db.exception.ManyObjectsForFunctionalRelationException; import org.simantics.db.exception.NoSingleResultException; import org.simantics.db.exception.ServiceException; import org.simantics.db.management.ISessionContext; +import org.simantics.db.procedure.Listener; import org.simantics.db.request.Read; import org.simantics.diagram.adapter.DefaultConnectionClassFactory; import org.simantics.diagram.adapter.FlagClassFactory; @@ -98,6 +99,7 @@ import org.simantics.utils.page.PageDesc; import org.simantics.utils.page.PageOrientation; import org.simantics.utils.threads.AWTThread; import org.simantics.utils.threads.IThreadWorkQueue; +import org.simantics.utils.threads.ThreadUtils; import org.simantics.utils.ui.ErrorLogger; @@ -290,6 +292,30 @@ public class DiagramSceneGraphProvider implements ICanvasSceneGraphProvider, IDi DiagramDesc diagramDesc = Simantics.getSession().syncRequest(DiagramRequests.getDiagramDesc(diagramResource)); if (diagramDesc != null) setDiagramDesc(ctx, diagramDesc); + + // Create a listener to react to page setting changes. + Simantics.getSession().asyncRequest(DiagramRequests.getDiagramDesc(diagramResource), new Listener() { + @Override + public void execute(DiagramDesc result) { + if (result != null && ctx != null) { + ThreadUtils.asyncExec(ctx.getThreadAccess(), () -> { + if (ctx != null) { + setDiagramDesc(ctx, result); + } + }); + } + } + + @Override + public void exception(Throwable t) { + ErrorLogger.defaultLogError(t); + } + + @Override + public boolean isDisposed() { + return DiagramSceneGraphProvider.this.ctx == null; + } + }); } catch (DatabaseException e) { ErrorLogger.defaultLogError(e); } @@ -298,7 +324,7 @@ public class DiagramSceneGraphProvider implements ICanvasSceneGraphProvider, IDi protected void setDiagramDesc(ICanvasContext ctx, DiagramDesc diagramDesc) { IHintContext hints = ctx.getDefaultHintContext(); hints.setHint(Hints.KEY_PAGE_DESC, diagramDesc.getPageDesc()); - //hints.setHint(Hints.KEY_DISPLAY_PAGE, diagramDesc.isPageBordersVisible()); + hints.setHint(Hints.KEY_DISPLAY_PAGE, diagramDesc.isPageBordersVisible()); hints.setHint(Hints.KEY_DISPLAY_MARGINS, diagramDesc.isMarginsVisible()); } diff --git a/bundles/org.simantics.modeling/META-INF/MANIFEST.MF b/bundles/org.simantics.modeling/META-INF/MANIFEST.MF index 067521a89..e00a8e114 100644 --- a/bundles/org.simantics.modeling/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.modeling/META-INF/MANIFEST.MF @@ -47,6 +47,7 @@ Export-Package: org.simantics.modeling, org.simantics.modeling.adapters, org.simantics.modeling.export, org.simantics.modeling.flags, + org.simantics.modeling.help, org.simantics.modeling.mapping, org.simantics.modeling.migration, org.simantics.modeling.preferences, diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLAction.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLAction.java index 47c7d3466..ba7e7117f 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLAction.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLAction.java @@ -8,11 +8,14 @@ import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.adapter.ActionFactory; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; -import org.simantics.diagram.Logger; import org.simantics.scl.runtime.function.Function1; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class SCLAction implements ActionFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(SCLAction.class); + final private Resource rule; public SCLAction(ReadGraph graph, Resource rule) throws DatabaseException { @@ -52,7 +55,7 @@ public class SCLAction implements ActionFactory { Function1 function = Simantics.getSession().syncRequest(new RuleFunctionRequest(rule)); function.apply(resource); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("SCLActionRunnable failed to request/apply RuleFunction {}", rule, e); } } diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLDropAction.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLDropAction.java index 74b19a214..f1d385545 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLDropAction.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLDropAction.java @@ -8,11 +8,14 @@ import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.adapter.DropActionFactory; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; -import org.simantics.diagram.Logger; import org.simantics.scl.runtime.function.Function3; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class SCLDropAction implements DropActionFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(SCLDropAction.class); + final private Resource rule; public SCLDropAction(ReadGraph graph, Resource rule) throws DatabaseException { @@ -55,7 +58,7 @@ public class SCLDropAction implements DropActionFactory { Function3 function = Simantics.getSession().syncRequest(new RuleFunctionRequest(rule)); function.apply(target, source, operation); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("SCLDropActionRunnable failed to request/apply RuleFunction {}", rule, e); } } diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/actions/Help.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/actions/Help.java index ba1243108..22327aeb3 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/actions/Help.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/actions/Help.java @@ -16,38 +16,36 @@ import org.simantics.Simantics; import org.simantics.databoard.Bindings; import org.simantics.db.Resource; import org.simantics.db.common.primitiverequest.PossibleRelatedValue2; -import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.adapter.ActionFactory; import org.simantics.modeling.ModelingResources; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Help implements ActionFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(Help.class); + @Override public Runnable create(Object target) { - - if(!(target instanceof Resource)) + if (!(target instanceof Resource)) return null; - final Resource resource = (Resource)target; - - return new Runnable() { - @Override - public void run() { - - try { - ModelingResources MOD = ModelingResources.getInstance(Simantics.getSession()); - String id = Simantics.sync(new PossibleRelatedValue2(resource, MOD.contextualHelpId, Bindings.STRING)); - if(id == null) { - PlatformUI.getWorkbench().getHelpSystem().displayDynamicHelp(); - return; - } - PlatformUI.getWorkbench().getHelpSystem().displayHelp(id); - } catch (DatabaseException e) { - Logger.defaultLogError(e); + final Resource resource = (Resource) target; + + return () -> { + try { + ModelingResources MOD = ModelingResources.getInstance(Simantics.getSession()); + String id = Simantics.sync(new PossibleRelatedValue2(resource, MOD.contextualHelpId, Bindings.STRING)); + if (id == null) { + PlatformUI.getWorkbench().getHelpSystem().displayDynamicHelp(); + return; } - + PlatformUI.getWorkbench().getHelpSystem().displayHelp(id); + } catch (DatabaseException e) { + LOGGER.error("Failed to display help for resource {}", resource, e); } }; } + } diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/help/HelpContexts.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/help/HelpContexts.java new file mode 100644 index 000000000..ca25cf417 --- /dev/null +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/help/HelpContexts.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2020 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: + * Semantum Oy- initial API and implementation + *******************************************************************************/ +package org.simantics.modeling.help; + +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.modeling.ModelingResources; +import org.simantics.modeling.PropertyVariables; +import org.simantics.utils.ui.AdaptionUtils; + +/** + * @author Tuukka Lehtonen + * @since 1.46.0 + */ +public class HelpContexts { + + /** + * @param graph + * @param resource + * @param variable + * @param selection optional ISelection + * @return + * @throws DatabaseException + */ + public static String getPossibleId(ReadGraph graph, Resource resource, Variable variable, Object selection) throws DatabaseException { + ModelingResources MOD = ModelingResources.getInstance(graph); + if (resource != null) { + Resource component = graph.getPossibleObject(resource, MOD.ElementToComponent); + String id = component != null ? graph.getPossibleRelatedValue2(component, MOD.contextualHelpId, Bindings.STRING) : null; + if (id != null) + return id; + id = graph.getPossibleRelatedValue2(resource, MOD.contextualHelpId, Bindings.STRING); + if (id != null) + return id; + } + + if (variable != null) { + String id = variable.getPossiblePropertyValue(graph, MOD.contextualHelpId, Bindings.STRING); + if (id != null) + return id; + } + + // TODO: consider removing this block + if (selection != null) { + PropertyVariables vars = AdaptionUtils.adaptToSingle(selection, PropertyVariables.class); + Variable var = vars != null ? vars.getConfiguration() : null; + String id = var != null ? var.getPossiblePropertyValue(graph, MOD.contextualHelpId, Bindings.STRING) : null; + if (id != null) + return id; + } + + return null; + } + + public static String getPossibleId(ReadGraph graph, Variable variable, String property) throws DatabaseException { + ModelingResources MOD = ModelingResources.getInstance(graph); + Variable prop = variable != null ? variable.getPossibleProperty(graph, property) : null; + return prop != null ? prop.getPossiblePropertyValue(graph, MOD.contextualHelpId, Bindings.STRING) : null; + } + +} diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/ComponentCopyAdvisor.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/ComponentCopyAdvisor.java index 3e6e9c1b9..021ecc436 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/ComponentCopyAdvisor.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/ComponentCopyAdvisor.java @@ -32,7 +32,6 @@ import org.simantics.modeling.ModelingUtils; import org.simantics.modeling.services.ComponentNamingUtil; import org.simantics.modeling.services.NamingException; import org.simantics.project.IProject; -import org.simantics.structural.stubs.StructuralResource2; import gnu.trove.map.hash.THashMap; @@ -58,7 +57,6 @@ public class ComponentCopyAdvisor extends GraphCopyAdvisor { @Override public Object copy(ISynchronizationContext context, WriteGraph graph, Resource source, Resource sourceContainer, Resource targetContainer, Map map) throws DatabaseException { - StructuralResource2 STR = StructuralResource2.getInstance(graph); Resource copy = CopyAdvisorUtil.copy2(graph, source, null, map); Layer0 L0 = Layer0.getInstance(graph); diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java index 8eed51aca..a70844cd3 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java @@ -12,6 +12,8 @@ import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.SyncListener; import org.simantics.db.request.Read; +import org.simantics.db.request.ReadExt; +import org.simantics.db.request.RequestFlags; import org.simantics.layer0.Layer0; import org.simantics.modeling.ModelingUtils; import org.simantics.modeling.internal.Activator; @@ -137,6 +139,29 @@ public enum GraphModuleSourceRepository implements ModuleSourceRepository { } } + static class PossibleResourceIU extends UnaryRead implements ReadExt { + + public PossibleResourceIU(String parameter) { + super(parameter); + } + + @Override + public Resource perform(ReadGraph graph) throws DatabaseException { + return graph.getPossibleResource(parameter); + } + + @Override + public boolean isImmutable(ReadGraph graph) throws DatabaseException { + return false; + } + + @Override + public int getType() { + return RequestFlags.IMMEDIATE_UPDATE; + } + + } + static class ReadModuleSource extends UnaryRead { public ReadModuleSource(String moduleName) { super(moduleName); @@ -144,7 +169,7 @@ public enum GraphModuleSourceRepository implements ModuleSourceRepository { @Override public ModuleSource perform(ReadGraph graph) throws DatabaseException { - Resource moduleResource = graph.getPossibleResource(parameter); + Resource moduleResource = graph.syncRequest(new PossibleResourceIU(parameter)); if(moduleResource == null) return null; Layer0 L0 = Layer0.getInstance(graph); diff --git a/bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ObserverGroupListener.java b/bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ObserverGroupListener.java index 31295b9b6..10e2abe67 100644 --- a/bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ObserverGroupListener.java +++ b/bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ObserverGroupListener.java @@ -44,7 +44,7 @@ public class ObserverGroupListener implements SetListener { public void add(Resource item) { //System.out.println("Add to group(" + this + "): " + item); items.put(item, item); - observer.update(); + observer.update(style, item); } @Override @@ -52,7 +52,7 @@ public class ObserverGroupListener implements SetListener { // new Exception().printStackTrace(); //System.out.println("Remove from group(" + this + "): " + item); items.remove(item); - observer.update(); + observer.update(style, item); } @Override diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ShapeNode2.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ShapeNode2.java new file mode 100644 index 000000000..2a8b9599a --- /dev/null +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ShapeNode2.java @@ -0,0 +1,191 @@ +/******************************************************************************* + * 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.scenegraph.g2d.nodes; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; + +import org.simantics.scenegraph.g2d.G2DNode; +import org.simantics.scenegraph.utils.GeometryUtils; +import org.simantics.scenegraph.utils.InitValueSupport; + +/** + * A scene graph node that renders a specified AWT {@link Shape} by optionally + * filling or drawing it. + * + * This is similar to ShapeNode, but allows separate stroke and fill colors. + * Due to API changes, I've done separate implementation. -MLuu + * + * + * @author luukkainen + * @author J-P Laine + * @author Tuukka Lehtonen + * + */ +public class ShapeNode2 extends G2DNode implements InitValueSupport { + + private static final long serialVersionUID = -5700299566608619380L; + + protected static final Stroke DEFAULT_STROKE = new BasicStroke(2); + + protected Shape shape = null; + protected Stroke stroke = DEFAULT_STROKE; + protected Paint strokeColor = Color.BLACK; + protected Paint fillColor = null; + protected boolean scaleStroke = false; + protected boolean scaleShape = false; + + protected transient Shape dynamicShape = null; + protected transient Stroke dynamicStroke = null; + protected transient Paint dynamicStrokeColor = null; + protected transient Paint dynamicFillColor = null; + protected transient Boolean dynamicScaleStroke = null; + protected transient Boolean dynamicScaleShape = null; + + @PropertySetter("shape") + @SyncField("shape") + public void setShape(Shape shape) { + this.shape = shape; + repaint(); + } + + @PropertySetter("stroke") + @SyncField("stroke") + public void setStroke(Stroke stroke) { + this.stroke = stroke; + } + + @PropertySetter("strokeColor") + @SyncField("strokeColor") + public void setStrokeColor(Paint color) { + this.strokeColor = color; + } + + @PropertySetter("fillColor") + @SyncField("fillColor") + public void setFillColor(Paint color) { + this.fillColor = color; + } + + + @SyncField("scaleStroke") + public void setScaleStroke(boolean scaleStroke) { + this.scaleStroke = scaleStroke; + } + + @SyncField("scaleShape") + public void setScaleShape(boolean scaleShape) { + this.scaleShape = scaleShape; + } + + @Override + public void render(Graphics2D g2d) { + Shape shape = dynamicShape != null ? dynamicShape : this.shape; + if (shape == null) + return; + + AffineTransform ot = setupRender(g2d); + renderShape(g2d, shape); + if (ot != null) + g2d.setTransform(ot); + } + + /** + * @param g2d + * @return current transform + */ + protected AffineTransform setupRender(Graphics2D g2d) { + AffineTransform old = null; + if (!transform.isIdentity()) { + old = g2d.getTransform(); + g2d.transform(transform); + } + + + boolean scaleShape = Boolean.TRUE.equals(dynamicScaleShape) ? true : this.scaleShape; + if (scaleShape) { + double xs = g2d.getTransform().getScaleX(); + double ys = g2d.getTransform().getScaleY(); + g2d.scale(1/xs, 1/ys); + } + + return old; + } + + protected void renderShape(Graphics2D g2d, Shape s) { + Paint color = dynamicFillColor != null ? dynamicFillColor : this.fillColor; + if (color != null) { + g2d.setPaint(color); + g2d.fill(s); + } + + Stroke stroke = dynamicStroke != null ? dynamicStroke : this.stroke; + if (stroke != null) { + color = dynamicStrokeColor != null ? dynamicStrokeColor : this.strokeColor; + if (color != null) g2d.setPaint(color); + + boolean scaleStroke = Boolean.TRUE.equals(dynamicScaleStroke) ? true : this.scaleStroke; + if (scaleStroke && stroke instanceof BasicStroke) { + BasicStroke bs = GeometryUtils.scaleStroke(stroke, (float) (1.0 / GeometryUtils.getScale(g2d.getTransform()))); + g2d.setStroke(bs); + } else { + g2d.setStroke(stroke); + } + + g2d.draw(s); + } + } + + @Override + public Rectangle2D getBoundsInLocal() { + if(shape == null) return null; + return shape.getBounds2D(); + } + + public void setValue(String key, Object value) { + if ("shape".equals(key)) + dynamicShape = (Shape) value; + else if ("stroke".equals(key)) + dynamicStroke = (Stroke) value; + else if ("strokeColor".equals(key)) + dynamicStrokeColor = (Paint) value; + else if ("fillColor".equals(key)) + dynamicFillColor = (Paint) value; + else if ("scaleStroke".equals(key)) + dynamicScaleStroke = (Boolean) value; + else if ("scaleShape".equals(key)) + dynamicScaleShape = (Boolean) value; +// else super.setValue(key, value); + } + + @Override + public void initValues() { + dynamicShape = null; + dynamicStroke = null; + dynamicStrokeColor = null; + dynamicFillColor = null; + dynamicScaleStroke = null; + dynamicScaleShape = null; + } + + @Override + public String toString() { + return super.toString() + " [shape=" + shape + ",color=" + strokeColor + ",fill=" + fillColor +"]"; + } + +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/repository/ModuleRepository.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/repository/ModuleRepository.java index 79b596908..23491235c 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/repository/ModuleRepository.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/repository/ModuleRepository.java @@ -240,6 +240,10 @@ public class ModuleRepository { return getModule(moduleName, null); } + public void update(String moduleName) { + getModuleEntry(moduleName, null).notifyAboutUpdate(); + } + public Failable getRuntimeModule(String moduleName, UpdateListener listener) { return getModuleEntry(moduleName, listener).getRuntimeModule(); } diff --git a/bundles/org.simantics.spreadsheet.common/META-INF/MANIFEST.MF b/bundles/org.simantics.spreadsheet.common/META-INF/MANIFEST.MF index b019ac5cc..3e2330afe 100644 --- a/bundles/org.simantics.spreadsheet.common/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.spreadsheet.common/META-INF/MANIFEST.MF @@ -6,7 +6,6 @@ Bundle-Version: 1.1.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-11 Require-Bundle: org.simantics.utils.datastructures;bundle-version="1.0.0", org.simantics.utils.ui;bundle-version="1.0.0", - org.apache.log4j;bundle-version="1.2.15", org.simantics.spreadsheet;bundle-version="1.1.0", org.simantics.db.layer0;bundle-version="1.1.0", org.simantics.scl.runtime;bundle-version="0.1.2", diff --git a/bundles/org.simantics/META-INF/MANIFEST.MF b/bundles/org.simantics/META-INF/MANIFEST.MF index 604255263..4829d00c5 100644 --- a/bundles/org.simantics/META-INF/MANIFEST.MF +++ b/bundles/org.simantics/META-INF/MANIFEST.MF @@ -11,7 +11,6 @@ Require-Bundle: org.eclipse.core.runtime;visibility:=reexport, org.simantics.project;bundle-version="1.0.1";visibility:=reexport, org.simantics.graph.db;bundle-version="1.1.5", org.eclipse.equinox.p2.metadata;bundle-version="2.0.0", - org.apache.log4j;bundle-version="1.2.15", org.simantics.layer0.utils;bundle-version="1.1.0", org.simantics.application;bundle-version="1.1.0", org.simantics.db.indexing;bundle-version="1.1.0", diff --git a/bundles/org.simantics/src/org/simantics/LogManager.java b/bundles/org.simantics/src/org/simantics/LogManager.java deleted file mode 100644 index 4274002c6..000000000 --- a/bundles/org.simantics/src/org/simantics/LogManager.java +++ /dev/null @@ -1,151 +0,0 @@ -/******************************************************************************* - * 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; - -import java.util.Properties; - -import org.apache.log4j.Hierarchy; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; -import org.apache.log4j.spi.LoggerFactory; -import org.apache.log4j.spi.RootLogger; - -/** - * This class encapsulates a Log4J Hierarchy and centralizes all Logger access. - */ -public class LogManager { - - private Hierarchy hierarchy; - - /** - * Creates a new LogManager. Saves the log and state location. - * Creates a new Hierarchy and add a new EventListener to it. - * Configure the hierarchy with the properties passed. Add this object to - * the list of active log managers. - * - * @param properties log configuration properties - */ - public LogManager(Properties properties) { - this.hierarchy = new Hierarchy(new RootLogger(Level.DEBUG)); - new PropertyConfigurator().doConfigure(properties, this.hierarchy); - } - - /** - * Checks if this PluginLogManager is disabled for this level. - * - * @param level level value - * @return boolean true if it is disabled - */ - public boolean isDisabled(int level) { - return this.hierarchy.isDisabled(level); - } - - /** - * Enable logging for logging requests with level l or higher. By default - * all levels are enabled. - * - * @param level level object - */ - public void setThreshold(Level level) { - this.hierarchy.setThreshold(level); - } - - /** - * The string version of setThreshold(Level level) - * - * @param level level string - */ - public void setThreshold(String level) { - this.hierarchy.setThreshold(level); - } - - /** - * Get the repository-wide threshold. - * - * @return Level - */ - public Level getThreshold() { - return this.hierarchy.getThreshold(); - } - - /** - * Returns a new logger instance named as the first parameter using the - * default factory. If a logger of that name already exists, then it will be - * returned. Otherwise, a new logger will be instantiated and then linked - * with its existing ancestors as well as children. - * - * @param clazz the class to get the logger for - * @return Logger - */ - public Logger getLogger(Class clazz) { - return this.hierarchy.getLogger(clazz.getName()); - } - - /** - * Returns a new logger instance named as the first parameter using the - * default factory. If a logger of that name already exists, then it will be - * returned. Otherwise, a new logger will be instantiated and then linked - * with its existing ancestors as well as children. - * - * @param name logger name - * @return Logger - */ - public Logger getLogger(String name) { - return this.hierarchy.getLogger(name); - } - - /** - * The same as getLogger(String name) but using a factory instance instead - * of a default factory. - * - * @param name logger name - * @param factory factory instance - * @return Logger - */ - public Logger getLogger(String name, LoggerFactory factory) { - return this.hierarchy.getLogger(name, factory); - } - - /** - * Returns the root of this hierarchy. - * - * @return Logger - */ - public Logger getRootLogger() { - return this.hierarchy.getRootLogger(); - } - - /** - * Checks if this logger exists. - * - * @return Logger - */ - public Logger exists(String name) { - return this.hierarchy.exists(name); - } - - /** - * Disposes the logger hierarchy - */ - public void shutdown() { - this.hierarchy.shutdown(); - } - - /** - * Resets configuration values to its defaults. - */ - public void resetConfiguration() { - this.hierarchy.resetConfiguration(); - } - -} \ No newline at end of file diff --git a/bundles/org.simantics/src/org/simantics/Simantics.java b/bundles/org.simantics/src/org/simantics/Simantics.java index cbe17e940..35808bd92 100644 --- a/bundles/org.simantics/src/org/simantics/Simantics.java +++ b/bundles/org.simantics/src/org/simantics/Simantics.java @@ -44,6 +44,7 @@ import org.simantics.db.management.SessionContextProvider; import org.simantics.db.management.SingleSessionContextProviderSource; import org.simantics.db.request.ReadInterface; import org.simantics.db.request.WriteInterface; +import org.simantics.db.service.XSupport; import org.simantics.internal.FileServiceImpl; import org.simantics.layer0.Layer0; import org.simantics.project.IProject; @@ -467,6 +468,14 @@ public class Simantics { } } + public static void saveQueries(Session session) { + try { + XSupport xs = session.getService(XSupport.class); + xs.saveQueries(); + } catch (Exception e) { + LOGGER.error("Saving database queries failed.", e); + } + } @SuppressWarnings({ "unchecked", "rawtypes" }) public static T applySCL(String module, String function, Object ... args) throws DatabaseException { diff --git a/bundles/org.simantics/src/org/simantics/SimanticsPlatform.java b/bundles/org.simantics/src/org/simantics/SimanticsPlatform.java index c5ed8fd1e..aa0b503da 100644 --- a/bundles/org.simantics/src/org/simantics/SimanticsPlatform.java +++ b/bundles/org.simantics/src/org/simantics/SimanticsPlatform.java @@ -1012,6 +1012,11 @@ public class SimanticsPlatform implements LifecycleListener { } catch (Throwable t) { LOGGER.error("Failed to flush index caches.", t); } + + if("true".equals(System.getProperty("org.simantics.db.persistQueries"))) { + progress.subTask("Saving Queries"); + Simantics.saveQueries(s); + } } progress.subTask("Close Database Session"); diff --git a/features/org.simantics.rcp.feature/feature.xml b/features/org.simantics.rcp.feature/feature.xml index 910e199de..54dd72372 100644 --- a/features/org.simantics.rcp.feature/feature.xml +++ b/features/org.simantics.rcp.feature/feature.xml @@ -479,13 +479,6 @@ This Agreement is governed by the laws of the State of New York and the intellec version="0.0.0" unpack="false"/> - - + + diff --git a/license.html b/license.html index cac8ec5bb..3d60be467 100644 --- a/license.html +++ b/license.html @@ -105,20 +105,6 @@ worth mentioning is ACE - Adaptive Communications Environment - - BSD 3-Clause License (http://www.cs.wustl.edu/~schmidt/ACE-copying.html) - -
Copyright (c) 2000-2005 INRIA, France Telecom
- - - JZlib - - BSD 3-Clause License (http://www.jcraft.com/jzlib/LICENSE.txt) - -
Copyright (c) 2000,2001,2002,2003,2004 ymnk, JCraft,Inc.
- - Batik (org.apache.batik) Apache Software License 2.0 @@ -148,7 +134,7 @@ All rights reserved. 1.2.3 - JSON (JSON_libraries) + Gson Apache Software License 2.0 @@ -169,14 +155,14 @@ All rights reserved. - JCommon, JFreeChart +JFreeChart LGPL - GNU Trove (gnu.trove2, gnu.trove3) + GNU Trove (gnu.trove3) LGPL @@ -254,7 +240,7 @@ Copyright (c) 2011-2016, Yann Collet EPL - 9.2.0 + 10.2.0 fastutil: Fast & compact type-specific collections for Java @@ -285,11 +271,12 @@ Copyright (c) 2011-2016, Yann Collet 21.0 - Aries + ANTLR v3 - Apache Software License 2.0 + BSD 3-Clause License (http://www.antlr3.org/license.html) - + 3.5.2 +
Copyright (c) 2010 Terence Parr
Apache Commons Codec @@ -341,13 +328,6 @@ Copyright (c) 2011-2016, Yann Collet 3.6.1 - Apache HttpClient 3 - - Apache Software License 2.0 - - 3.1.0 - - Apache POI Apache Software License 2.0 @@ -355,14 +335,6 @@ Copyright (c) 2011-2016, Yann Collet 3.15 - ANTLR v3 - - BSD 3-Clause License (http://www.antlr3.org/license.html) - - 3.5.2 -
Copyright (c) 2010 Terence Parr
- - Apache Lucene Core Apache Software License 2.0 @@ -384,6 +356,13 @@ Copyright (c) 2011-2016, Yann Collet 2.6.0, only needed by Apache POI + Aries + + Apache Software License 2.0 + + + + curvesapi BSD 3-Clause License (https://github.com/virtuald/curvesapi/blob/master/license.txt), Apache Software License 2.0 diff --git a/releng/org.simantics.sdk.build.p2.site/pom.xml b/releng/org.simantics.sdk.build.p2.site/pom.xml index 9534f71fb..4d84e674f 100644 --- a/releng/org.simantics.sdk.build.p2.site/pom.xml +++ b/releng/org.simantics.sdk.build.p2.site/pom.xml @@ -42,6 +42,7 @@ 0.5.4 4.4 1.20 + 1.6 2.6 1.2 1.4 @@ -270,6 +271,10 @@ org.apache.commons.compress + + org.apache.commons:commons-csv:${commons-csv.version} + true + commons-lang:commons-lang:${commons-lang.version} true diff --git a/releng/org.simantics.sdk.build.targetdefinition/org.simantics.sdk.build.targetdefinition.target b/releng/org.simantics.sdk.build.targetdefinition/org.simantics.sdk.build.targetdefinition.target index 708e508ed..6500ce550 100644 --- a/releng/org.simantics.sdk.build.targetdefinition/org.simantics.sdk.build.targetdefinition.target +++ b/releng/org.simantics.sdk.build.targetdefinition/org.simantics.sdk.build.targetdefinition.target @@ -281,6 +281,8 @@ + + diff --git a/releng/org.simantics.sdk.build.targetdefinition/org.simantics.sdk.build.targetdefinition.tpd b/releng/org.simantics.sdk.build.targetdefinition/org.simantics.sdk.build.targetdefinition.tpd index 6a0428e20..7494c7981 100644 --- a/releng/org.simantics.sdk.build.targetdefinition/org.simantics.sdk.build.targetdefinition.tpd +++ b/releng/org.simantics.sdk.build.targetdefinition/org.simantics.sdk.build.targetdefinition.tpd @@ -282,6 +282,8 @@ location "http://www.simantics.org/download/master/external-components/maven/" { org.apache.commons.collections4.source org.apache.commons.compress org.apache.commons.compress.source + org.apache.commons.csv + org.apache.commons.csv.source org.apache.commons.io org.apache.commons.io.source org.apache.commons.lang diff --git a/releng/org.simantics.sdk.build.targetdefinition/simantics.target b/releng/org.simantics.sdk.build.targetdefinition/simantics.target index 10ff40e65..2e8f54c2d 100644 --- a/releng/org.simantics.sdk.build.targetdefinition/simantics.target +++ b/releng/org.simantics.sdk.build.targetdefinition/simantics.target @@ -281,6 +281,8 @@ + + diff --git a/tests/org.simantics.db.tests/META-INF/MANIFEST.MF b/tests/org.simantics.db.tests/META-INF/MANIFEST.MF index 71a1b9653..1d2330566 100644 --- a/tests/org.simantics.db.tests/META-INF/MANIFEST.MF +++ b/tests/org.simantics.db.tests/META-INF/MANIFEST.MF @@ -13,7 +13,6 @@ Require-Bundle: org.eclipse.core.runtime, org.simantics.db.management;bundle-version="0.8.0", gnu.trove3;bundle-version="3.0.3", org.simantics.fastlz;bundle-version="1.0.0", - org.apache.log4j;bundle-version="1.2.15", org.simantics.db.impl;bundle-version="0.8.0", org.simantics.db.layer0;bundle-version="0.8.0", org.simantics.project;bundle-version="1.0.1", diff --git a/tests/org.simantics.db.tests/build-installer.xml b/tests/org.simantics.db.tests/build-installer.xml index 05804fb84..80b7f7b9d 100644 --- a/tests/org.simantics.db.tests/build-installer.xml +++ b/tests/org.simantics.db.tests/build-installer.xml @@ -21,12 +21,11 @@ - - - + + @@ -35,10 +34,6 @@ - - - - diff --git a/tests/org.simantics.db.tests/build.xml b/tests/org.simantics.db.tests/build.xml index da0a86faa..4c6a1daf9 100644 --- a/tests/org.simantics.db.tests/build.xml +++ b/tests/org.simantics.db.tests/build.xml @@ -135,7 +135,6 @@ -