Only few parts transferred and somehow quickly reformatted for now.
Lots of work remaining.
refs #7674
Change-Id: I1cf8b6a3da5ec14064f79d0a0c765899be1d8872
--- /dev/null
+_book/\r
+node_modules/
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>platform-docs</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ </buildSpec>\r
+ <natures>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+## Overview\r
+\r
+The testing framework is contained in the plug-in **org.simantics.db.testing**.\r
+\r
+This section covers a JUnit-based testing framework for making tests, which use the Simantics Database. The framework handles two separate cases\r
+\r
+* POJO JUnit tests, where tests are executed without OSGi and with some configuration restrictions\r
+* OSGi JUnit tests, where tests are executed in OSGi based on the current workspace\r
+\r
+The framework contains\r
+\r
+* Test case templates for extending in org.simantics.db.testing.base\r
+* Generic test cases in org.simantics.db.testing.cases\r
+\r
+## General\r
+\r
+Both testing approaches use similar test suites. Below is an example\r
+\r
+~~~\r
+public class Tests {\r
+\r
+ public static Test suite() throws Exception {\r
+\r
+ TestSuite suite = new TestSuite("My suite");\r
+\r
+ //$JUnit-BEGIN$\r
+ suite.addTestSuite(FreshDatabaseTest.class);\r
+ suite.addTestSuite(MyTest.class);\r
+\r
+ //$JUnit-END$\r
+ return suite;\r
+\r
+ }\r
+\r
+}\r
+~~~\r
+\r
+The first test is used to set up the initial database and upon which the other tests operate. In POJO mode the first test also needs to give some configuration settings as described below.\r
+\r
+## Templates\r
+\r
+### FreshDatabaseTest\r
+\r
+This test can be used to initialize a database with only selected ontologies installed. The test can be run as is or it can be extended to perform tests upon the initialized database. Use getSession() for obtaining the session.\r
+\r
+### ExistingDatabaseTest\r
+\r
+This test can be used to run tests upon an existing database (created e.g. with FreshDatabaseTest). Use getSession() for obtaining the session.\r
+\r
+### WriteReadTest\r
+\r
+This test can be used to run simple write-first-then-read tests upon an existing database. Override methods write and read to perform testing.\r
+\r
+## Running the tests\r
+\r
+To run the tests open a context menu for the suite class (see example above) and\r
+\r
+* To run in POJO, select Run As .. JUnit Test\r
+* To run in OSGi, select Run As .. JUnit Plug-in Test\r
+\r
+The Plug-in tests need to be run as 'all workspace and enabled target plug.ins' and as application '[No Application] - Headless Mode]'\r
+\r
+Note that the launchers can be configured using .launch - files.\r
+\r
+## POJO details\r
+\r
+The POJO testing framework can be set up by running a customized org.simantics.db.testing.cases.FreshDatabaseTest e.g.\r
+\r
+~~~\r
+public class InitializationTest extends FreshDatabaseTest {\r
+\r
+ @Override\r
+ public void configure(TestSettings settings) {\r
+\r
+ settings.setAdapters(new String[] {\r
+ "org.simantics.db.layer0/adapters.xml",\r
+ "org.simantics.spreadsheet.graph/adapters.xml"\r
+ });\r
+ settings.setOntologies(new String[] {\r
+ "/org.simantics.spreadsheet.ontology/graph.tg",\r
+ });\r
+\r
+ settings.setWorkspace(new File(".."));\r
+ settings.setInitialized();\r
+\r
+ }\r
+\r
+}\r
+~~~\r
+\r
+## OSGi details\r
+\r
+The Plug-in testing framework applies all adapters found from the workspace.\r
+\r
+org.simantics.db.testing.cases.FreshDatabaseTest can be used to install all available ontologies from the workspace.\r
--- /dev/null
+# Intro\r
+\r
+This section deals with the following specifications\r
+\r
+* Specification of generic functions applicable in the Simantics framework\r
+* Specification of functions attached to types (methods)\r
+* Specification of functions with side-effects (operations or commands)\r
+* Automatically generated code based on semantic model about functions (stubs)\r
+\r
+## Specification\r
+\r
+* Functions are objects implementing the interface `org.simantics.scl.runtime.function.Function`.\r
+* We have a type `Value` (?) that can be adapted to an SCL value (in particular to a function).\r
+* We have a relation `HasType` (?) Value -> String that specifies the SCL type of the value\r
+* Operations are functions that return an object implementing `WriteResult`.\r
--- /dev/null
+# Interface summary\r
+\r
+## General\r
+\r
+### org.simantics.Simantics\r
+\r
+This static class can be used to obtain the active Session.\r
+\r
+### org.simantics.db.Session\r
+\r
+The Session interface represents the connection into the semantic database. Implements e.g. `RequestProcessor` and serves various special interfaces via the `getService`-method.\r
+\r
+## Reading and writing\r
+\r
+### org.simantics.db.RequestProcessor\r
+\r
+`RequestProcessor` is a synchronous interface for making read queries and writes to the semantic database. Main implementations are `Session`, `ReadGraph` and `WriteGraph`.\r
+\r
+### org.simantics.db.Read\r
+\r
+The interface Read represents a query, which produces a single result. Main implementations are `ResourceRead*` and `*naryRead`.\r
+\r
+### org.simantics.db.Write\r
+\r
+The interface `Write` represents a modification into the semantic database. Main implementation is `WriteRequest`.\r
--- /dev/null
+According to [[:Media:Layer0.pdf|Layer0]] semantics, relations <em>can</em> have inverse relations. For the database and client this means that when claiming new statements <code>(s, p, o)</code> using\r
+ WriteGraph.claim(Resource subject, Resource predicate, Resource object)\r
+an inverse statement <code>(o, inv(p), s)</code> will be automatically claimed into the database. Some statements are such that they tend to raise the degree of the resource (amount of incoming/outgoing relations) to very large numbers. The database is not built to efficiently handle such resources. One such relation is ''InstanceOf'' which is a statement that pretty much each and every resource in the database has. It does not have an inverse relation, but considering it had one like ''HasInstance'', here's what would happen. For example, for each ''L0.String'' instance created an inverse statement would be added <code>(L0.String, L0.HasInstance, :L0.String)</code> statement into the database, thereby enlarging the degree of ''L0.String''. When working with larger databases this would most likely become a problem.\r
+\r
+To make it possible to optimize this situation we provide the possibility to skip adding of inverse relations when claiming statements into the database by using\r
+ WriteGraph.claim(Resource subject, Resource predicate, Resource inverse, Resource object)\r
+with a <code>null</code> inverse relation argument to create the sensitive statements such as ''InstanceOf''-relations.\r
--- /dev/null
+It is possible to define procedural values in the graph and compute their values using graph interface.\r
+\r
+Currently the methods for computing the values are:\r
+* <T> T getRelatedValue2(Resource subject, Resource relation) throws DatabaseException;\r
+* <T> T getPossibleRelatedValue2(Resource subject, Resource relation) throws DatabaseException;\r
+* <T> T getRelatedValue2(Resource subject, Resource relation, Object context) throws DatabaseException;\r
+* <T> T getPossibleRelatedValue2(Resource subject, Resource relation, Object context) throws DatabaseException;\r
+* <T> T getRelatedValue2(Resource subject, Resource relation, Binding binding) throws DatabaseException;\r
+* <T> T getPossibleRelatedValue2(Resource subject, Resource relation, Binding binding) throws DatabaseException;\r
+* <T> T getRelatedValue2(Resource subject, Resource relation, Object context, Binding binding) throws DatabaseException;\r
+* <T> T getPossibleRelatedValue2(Resource subject, Resource relation, Object context, Binding binding) throws DatabaseException;\r
+\r
+These methods work like getRelatedValue and getPossibleRelatedValue -methods. They follow the given relation from the given subject and then determine the value based on the resource found. If the resource is a literal, then they work exactly like getRelatedValue and getPossibleRelatedValue. They however extend the old functionality in two ways:\r
+* If the found resource is an instance of ExternalValue, then the URI of the resource is used to find a value that is declared using extensions and Java annotations.\r
+* If the found resource is an instance of Value, the mechanism first finds the property ConvertsToValueWith of the value and uses it compute the value.\r
+These two mechanisms are detailed below.\r
+\r
+## External values\r
+\r
+External values are resources in the graph with type ExternalValue. They must have URIs. Let's consider for example\r
+ SEL.Functions.inputModifier : L0.ExternalValue\r
+defined in SelectionView -ontology.\r
+\r
+The definitions of the values are declared in the extension point `org.simantics.scl.reflection.binding` like this\r
+\r
+~~~\r
+ <extension point="org.simantics.scl.reflection.binding">\r
+ <namespace path="http://www.simantics.org/SelectionView-0.0/Functions">\r
+ <externalClass className="org.simantics.db.Resource"/>\r
+ <externalClass className="org.simantics.db.ReadGraph"/>\r
+ <externalClass className="org.simantics.db.WriteGraph"/>\r
+ <externalClass className="org.simantics.db.layer0.variable.Variable"/>\r
+ <class className="org.simantics.selectionview.function.All"/>\r
+ </namespace>\r
+ </extension>\r
+~~~\r
+\r
+The value itself is defined as:\r
+~~~\r
+public class All {\r
+ @SCLValue(type = "WriteGraph -> Variable -> a -> b -> String")\r
+ public static String inputModifier(WriteGraph graph, Variable variable, Object value, Object _binding) throws DatabaseException {\r
+ ...\r
+ }\r
+}\r
+~~~\r
+\r
+Any static method or field can be declared an external value with `@SCLValue` annotation. The SCL -type of the value is given as an attribute to the annotation. By default the method name and resource name are matched, but the method name can be overridden in the annotation with name attribute.\r
+\r
+## Contextual values\r
+\r
+External values can be used to define complex constants, in particular functions. Contextual values extend the functionality so that the value may depend on the other properties of the original subject resource that was used for finding the value resource. In some cases, even more needs to be known about the context of the computation than just a resource. Therefore some of the `getRelatedValue2` -methods take a context as a parameter. If it is not given, the default context is the subject resource.\r
+\r
+A contextual value is defined as a resource with type `Value` and properties `ConvertsToValueWith`. For example:\r
+\r
+~~~\r
+ L0.List <T L0.Value\r
+ L0.HasDescription """Represents a list of resources that may contain repetitions."""\r
+ L0.HasValueType "[Resource]"\r
+ @L0.assert L0.ConvertsToValueWith L0.Functions.listResources : L0.ExternalValue \r
+~~~\r
+\r
+The conversion function must have type\r
+\r
+ ReadGraph => Resource -> Context -> Result\r
+\r
+The second parameter is the resource of the value itself (in this case the linked list) and the context type can be any type. Result type must be the type annotated with `HasValueType`.\r
+\r
+## Value types\r
+\r
+Types of the values must be annotated with relation `HasValueType`. The type is an SCL type in a string format. A relation may require that its range has a certain value type using `RequiresValueType` -property.\r
--- /dev/null
+## Problem Statement\r
+\r
+No language can define itself. There have to be extra-language mechanisms for defining basic concepts of the language. For\r
+computers to understand the language, this means some code. Here is a basic example:\r
+\r
+~~~\r
+public class ShapeFactory {\r
+ public static Shape create(Graph g, Resource r) {\r
+ ShapeResources sr = ShapeResource.getInstance(g);\r
+ if(g.isInstanceOf(r, sr.Rectangle)) {\r
+ ...\r
+ return new Rectangle2D.Double(...);\r
+ }\r
+ else if(g.isInstanceOf(r, sr.Ellipse)) {\r
+ ...\r
+ return new Ellipse2D.Double(...);\r
+ }\r
+ ...\r
+\r
+ throw new IllegalArgumentException("Resource is not a shape or the shape is unsupported.");\r
+ }\r
+}\r
+~~~\r
+\r
+This works as long as there is only a fixed set of shapes. Addition of every new shape needs modification to the code.\r
+We would like to have something like:\r
+* A declaration telling that instances of Shape can be adapted to objects of Shape class.\r
+* For each concrete subtype of Shape, a code creating an object of the corresponding Shape class.\r
+* Declarations connecting subtypes and code snippets.\r
+* Utility that implements the creation pattern.\r
+\r
+## Solution\r
+\r
+Declarations are written into adapters.xml-file that has to be located in the plugin root:\r
+\r
+~~~\r
+<?xml version="1.0" encoding="UTF-8"?>\r
+<adapters>\r
+\r
+ <target interface="org.simantics.form.model.IWidgetModel">\r
+ <baseType uri = "http://www.simantics.org/Form-1.0/Widget"/>\r
+ <type uri = "http://www.simantics.org/Form-1.0/Label"\r
+ class = "org.simantics.form.model.adapters.LabelAdapter"/>\r
+ <type uri = "http://www.simantics.org/Form-1.0/InputText"\r
+ class = "org.simantics.form.model.adapters.InputTextAdapter"/>\r
+ ...\r
+ </target>\r
+\r
+ <target interface="org.simantics.form.model.ILayoutModel">\r
+ <baseType uri = "http://www.simantics.org/Form-1.0/Layout"/>\r
+\r
+ <!--\r
+ Direct adaption to the specified class via\r
+ constructor and possible arguments\r
+ -->\r
+ <type uri = "http://www.simantics.org/Form-1.0/GridLayout"\r
+ class = "org.simantics.form.model.adapters.GridLayout">\r
+ <graph/>\r
+ <this/>\r
+ </type>\r
+\r
+ <!--\r
+ A procedural adapter definition. adapterClass implements\r
+ org.simantics.db.adaption.Adapter to construct an instance\r
+ of the target interface.\r
+ -->\r
+ <adapter uri="http://www.simantics.org/Form-1.0/FormLayout"\r
+ adapterClass="org.simantics.form.model.adapters.FormLayoutAdapter" />\r
+ </target>\r
+\r
+</adapters>\r
+~~~\r
+\r
+Each `<target>...</target>` section defines adaption to given interface.\r
+\r
+`<baseType>` gives one or more types where all classes implementing the adaption have been inherited from.\r
+\r
+`<type>` defines direct adaptation from instances of given type (**uri**) by construction the specified class (**class**) through Java Reflection API's using static method (**constructor**) if specified and a constructor of the class otherwise whereas `<adapter>` defines adaptation from instances of given type (**uri**) by using the given adapter (**adapterClass**). The adapter has to implement the following interface:\r
+\r
+~~~\r
+public interface Adapter<T> {\r
+ void adapt(AsyncReadGraph g, Resource r, AsyncProcedure<T> procedure);\r
+}\r
+~~~\r
+\r
+In addition the adapter may contain this kind of definitions:\r
+\r
+~~~\r
+ <resource uri="http://www.simantics.org/Layer0-1.0/OrderedSetElements"\r
+ class="org.simantics.layer0.utils.binaryPredicates.OrderedSetElementsPredicate"/>\r
+~~~\r
+\r
+This means that the resource defined by the uri is always adapted to an instance of the given class.\r
+\r
+The main difference between `<type>`/`<resource>` definitions and `<adapter>` definitions is that `<type>`/`<resource>` adaptation cannot be used for complex adaptation since both can only be used to adapt to instances of the defined adapter class and nothing else. `<adapter>` on the other hand can perform more complex analysis and return any instance of the adaptation target interface.\r
+\r
+Defined adapters can be used with the following synchronous methods, where `clazz`-parameter refers to the interface in the adapter declaration:\r
+\r
+~~~\r
+public interface ReadGraph {\r
+ ....\r
+ <T> T adapt(Resource resource, Class<T> clazz)\r
+ throws AdaptionException, ValidationException, ServiceException;\r
+\r
+ <T> T adaptUnique(Resource resource, Class<T> clazz)\r
+ throws AdaptionException, ValidationException, ServiceException;\r
+\r
+ <T> T getPossibleAdapter(Resource resource, Class<T> clazz)\r
+ throws ValidationException, ServiceException;\r
+\r
+ <T> T getPossibleUniqueAdapter(Resource resource, Class<T> clazz)\r
+ throws ValidationException, ServiceException;\r
+ ...\r
+}\r
+~~~\r
+\r
+For details, see [[svn:db/trunk/org.simantics.db/src/org/simantics/db/ReadGraph.java|ReadGraph interface]].\r
+\r
+In addition to `<adapter>`-elements, the file may contain `<installer>`-elements, with *class*-attribute referring to an implementation of the interface:\r
+\r
+~~~\r
+public interface AdapterInstaller {\r
+ void install(ReadGraph g, AdaptionService service) throws Exception;\r
+}\r
+~~~\r
+\r
+where\r
+\r
+~~~\r
+public interface AdaptionService {\r
+ <T> void adapt(AsyncReadGraph g,\r
+ Resource r, Class<T> clazz, boolean possible,\r
+ AsyncProcedure<T> procedure);\r
+\r
+ <T> void adaptNew(AsyncReadGraph g,\r
+ Resource r, Class<T> clazz, boolean possible,\r
+ AsyncProcedure<T> procedure);\r
+\r
+ <T> void declareAdapter(Resource type, Class<T> clazz);\r
+\r
+ <T> void addAdapter(Resource type, Class<T> clazz, Adapter<T> adapter);\r
+\r
+ <T> void addInstanceAdapter(Resource resource, Class<T> clazz, Adapter<T> adapter); \r
+}\r
+~~~\r
+\r
+The class installs adapters by using method `addAdapter` (and `addInstanceAdapter`).\r
+You should use the xml-file to define your adapters if possible. The installer-mechanism is provided for cases where you want to install an adapter that is constructed with special parameters.\r
+\r
+### Direct Adapters\r
+\r
+Direct adapters are used, when the user has a Resource and wants a specific Java interface e.g. for 2D diagrams, the user has an instance of DIA.Element and obtains an instance of org.simantics.diagram.adapter.ElementFactory. The Java instance can operate on the given resource for data-driven implementation of the ElementFactory.\r
+\r
+### Related Adapters\r
+\r
+Related adapters are used, when the user has a relation Resource and a subject Resource and wishes to obtain a Java interface associated to the L0.HasRange of the predicate, configured by a single statement defined by subject and relation. The adapter implementations are bound to the object Resource of the defining statement. The adapter implementation obtains the defining statement as parameter for data-driven implementation.\r
+\r
+An example:\r
+\r
+~~~\r
+L0X.StringAdapter <T L0X.StatementAdapter\r
+L0.String <T L0.Literal <T L0X.StringAdapter\r
+\r
+L0.HasLabel <R L0.HasProperty : L0.FunctionalRelation\r
+ L0.HasRange L0X.StringAdapter\r
+~~~\r
+\r
+L0X.StringAdapter is defined so that it requires an implementation of an adapter to java.lang.String (there is currently no syntax yet for this).\r
+\r
+L0.HasLabel is defined so that it refers to an object, which can be adapted to java.lang.String. This directs the user to obtain labels by using the adapter instead of expecting a L0.String. Thus we can make arbitrary data-driven and procedural implementations of this property.\r
+\r
+## Construction-time Parameters\r
+Certain parameters can be specified for adapters defined with `<type>` and `<resource>` elements. These arguments will be directly forwarded to a constructor matching this argument list in your adapter implementation class.\r
+\r
+\r
+| Term | Description |\r
+|--------|--------|\r
+|`<this/>`|The resource that is being adapted.|\r
+|`<graph/>`|`ReadGraph` for reading the graph database during construction of the adapted class instance.|\r
+|`<bundle/>`|`Bundle` class instance which identifies the bundle in which this adapter is defined. Can also be used to specify the referenced bundle explicitly using its symbolic name, e.g. `<bundle>bundle.id</bundle>`.|\r
+|`<string>FOO</string>`|Any string constant contained as text within the <string> tag. Passed to the constructor as a `java.lang.String` instance.|\r
+|`<single/>`|Requires attribute uri which must specify a URI to a relation resource. If adaption is performed for resource S, this argument element looks for a single object O from the statement (S, R, O) and passes O as an argument to the adapter class. If no single object O exists, the adapter is given null.|\r
+|`<related/>`|Requires attribute uri which must specify a URI to a relation resource. If adaption is performed for resource S, this argument element looks for all objects O existing in the database (S, R, O) and the objects to the adapter as a `Collection<Resource>`.|\r
+|`<orderedSet/>`|Requires attribute uri which must specify a URI to an ordered set resource. Looks for the specified URI in the database, assumes it is an ordered set resource and loads the whole ordered set into a Collection<Resource> instance. This collection is passed as an argument to the adapter class.|\r
+\r
+## See Also\r
+\r
+[XML schema for adapter definition XML files](TODO: link to adapters.xsd)\r
--- /dev/null
+Serializing a resource\r
+\r
+~~~\r
+ long serializeResource(RequestProcessor processor, Resource resource) throws DatabaseException {\r
+ SerialisationSupport ss = processor.getService(SerialisationSupport.class);\r
+ return ss.getRandomAccessId(resource);\r
+ }\r
+ String serializeResourceToString(RequestProcessor processor, Resource resource) throws DatabaseException {\r
+ return String.valueOf(serializeResource(processor, resource));\r
+ }\r
+~~~\r
+\r
+Deserializing a resource\r
+\r
+~~~\r
+ Resource deserializeResource(ReadGraph graph, long randomAccessId) throws DatabaseException {\r
+ SerialisationSupport ss = session.getService(SerialisationSupport.class);\r
+ return rs.getResource(randomAccessId);\r
+ }\r
+ Resource deserializeResource(ReadGraph graph, String randomAccessId) throws DatabaseException, NumberFormatException {\r
+ return deserializeResource(graph, Long.parseLong(randomAccessId));\r
+ }\r
+~~~\r
--- /dev/null
+## Overview\r
+\r
+A subgraph extent is a set of statements bound by a given set of root resources. Subgraph extents are needed in\r
+\r
+* Copy-paste\r
+* Import and export\r
+* Delete\r
+\r
+## Domain\r
+\r
+A subgraph extent domain is the set of resources for which all parent resources are included in the root set. The set of parents for resource *r* are found by\r
+\r
+* including all resources `par` for statements `(r, p <R http://www.simantics.org/Layer0-1.0/PartOf, par)`\r
+* including all containing ordered sets `ord` from statements `(*r*, *ord* <R http://www.simantics.org/Layer0-1.0/HasNext, _)` where `ord` is not `r`.\r
+\r
+If the preceding procedure yielded no parents then the parent set is determined by\r
+\r
+* including all resources `par` for statements `(par, p <R http://www.simantics.org/Layer0-1.0/IsRelatedTo, r)`\r
+\r
+## Extent descriptions\r
+\r
+The set of statements in a subgraph extent is determined by applying subgraph extent descriptions to the domain resources. The extent descriptions are specified in ontologies and attached to types. An extent description is implemented using the following adapter class\r
+\r
+~~~\r
+public interface SubgraphExtent {\r
+\r
+ interface Callback {\r
+ void statement(ReadGraph graph, Statement statement) throws DatabaseException;\r
+ void value(ReadGraph graph, Resource resource, byte[] value) throws DatabaseException;\r
+ }\r
+\r
+ Set<Resource> types(ReadGraph graph) throws DatabaseException;\r
+ void traverse(ReadGraph graph, Resource resource, Collection<Resource> domain, Callback callback) throws DatabaseException;\r
+\r
+}\r
+~~~\r
+\r
+## Extent determination procedure\r
+\r
+* Determine the domain set by walking `IsRelatedTo` from root set and the discovered domain.\r
+* Determine the set of extent descriptions found from root set dependencies (ontologies).\r
+* Divide the set of available extent descriptions into included and excluded sets.\r
+* Determine the set of (potentially) included statements by applying included extent descriptions on the domain set\r
+* Determine the set of excluded statements by applying excluded extent descriptions on the domain set\r
+* Remove the set of excluded statements from the included statement set\r
--- /dev/null
+This page documents a simple global non-contextual undo/redo mechanism.\r
+\r
+## Mechanism\r
+\r
+Database client keeps a global list of undoable/redoable operations. Operations are added to undo list during commit. Each commit creates a change set to server which defines the changes to resource values and statements. Change set also contains metadata for interpreting the change. The metadata format is defined by client and the server can not read or interpret it. Each operation has a unique change set identifier. Sequential operations are tagged as combined by giving them the same operation id. All operations with same id will be treated as single undoable/redoable operation.\r
+\r
+### Combining write requests\r
+\r
+Currently there is only one way to combine several database write requests into a single operation.\r
+\r
+Normally an operation is created out of each separate write transaction. This happens when write transactions are initiated by invoking **Session.async/asyncRequest**. To combine a separate write transaction into a single operation, the write request must be initiated from within the write transaction using any **WriteGraph.async/asyncRequest** interface methods. The database client will group all write transaction change sets initiated like this into one operation.\r
+\r
+## Undo and redo handling in the Simantics workbench\r
+\r
+If **org.eclipse.ui.edit.undo** and **org.eclipse.ui.edit.redo** commands are bound to handlers **Session{Undo,Redo}Handler** then the undo/redo mechanism is activated. The handlers undo/redo one operation from the global undo/redo lists with each button press. It is desirable that each developer who develops requests that modify the graph comment their changes as shown by the following example.\r
+\r
+~~~\r
+ session.sync(new WriteRequest() {\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ // Do your modifications.\r
+ Layer0 b = Layer0.getInstance(graph);\r
+ Resource s = graph.newResource();\r
+ graph.claim(s, b.InstanceOf, b.Entity);\r
+\r
+ // Add comment to change set.\r
+ CommentMetadata cm = graph.getMetadata(CommentMetadata.class);\r
+ cm.add("My comment.");\r
+ graph.addMetadata(cm);\r
+ }\r
+ });\r
+~~~\r
+\r
+You can test your operations using the following procedure:\r
+\r
+* Do the operation.\r
+* Check from ''Teamwork'' / ''Graph History'' view which change sets have been created and that they are commented properly.\r
+\r
+## Marking undo-points in database version history\r
+\r
+Should the user simply perform write requests as described in [[#Undo and redo handling in the Simantics workbench]], each write request would simply create a new version into the database version history but all the changes would simply pile up into a single undoable operation.\r
+\r
+The database API has two methods for telling the database that it's current persistent state should be regarded as an undo point and new undoable operation should be started. These are in interfaces <code>org.simantics.db.session</code> and <code>org.simantics.db.WriteOnlyGraph</code>:\r
+\r
+~~~\r
+public interface Session extends RequestProcessor { \r
+ ...\r
+ /**\r
+ * Marks the current database state or the beginning of the current ongoing\r
+ * write transaction as an undo point. Calling this method several times\r
+ * before or during the same write transaction has no effect.\r
+ */\r
+ void markUndoPoint();\r
+ ...\r
+}\r
+\r
+\r
+public interface WriteOnlyGraph extends ServiceLocator, MetadataI {\r
+ ...\r
+ /**\r
+ * Marks the beginning of the ongoing write transaction as an undo point.\r
+ * Calling this method several times during the same transaction has no\r
+ * effect.\r
+ */\r
+ void markUndoPoint();\r
+ ...\r
+}\r
+~~~\r
+\r
+## Related Documents\r
+\r
+* TODO: consider: [[Undo and Redo]] - internals of the mechanism.\r
--- /dev/null
+# Intro\r
+\r
+The Variable interface provides an uniform access model to data in Simantics. It includes\r
+\r
+* Tree-structured address space for accessing model **structure** and **properties**\r
+* Uniform access to model **configuration** and **state**\r
+\r
+Key use cases include\r
+\r
+* Browsing of the **model configuration and states** (see [[Model Browser]])\r
+* **Manipulation of objects** (see [[Selection View]])\r
+* Representation of **tabular data** (see [[Spreadsheets]])\r
+\r
+Main functional requirements include representation of\r
+\r
+* **Structural models** with **procedural** features (see [[Structural]])\r
+* **Runtime** data of solvers (see [[Experiments]])\r
+* **Historical** data from experiments\r
+* **Ontological** data\r
+\r
+# Solution\r
+\r
+**Variable** is a tree-structured view into the Simantics data model. Each variable is either a **child** or a **property** and can further contain own children and properties. The difference between a child and a property is that a property contains a **value**.\r
+\r
+The variable space browsing methods are used to obtain\r
+\r
+* all children\r
+* children by name\r
+* all properties\r
+* properties by name\r
+* variable by **path**\r
+* **parent** variable\r
+\r
+Other services are\r
+\r
+* accessing (get/set) the value of a property variable\r
+* querying adapter interfaces\r
+\r
+A set of built-in properties is required for all variables. These properties have also dedicated interface methods.\r
+\r
+* **URI**, which is an unique string identifier and locator of the variable in the tree structure\r
+* **Parent**, which is the tree parent of the variable\r
+* **HasName**, which is a local identifier for the variable within its parent. Names are also used to create URIs.\r
+* **HasLabel**, which is a short textual representation of the variable\r
+* **hasStandardResource**, which returns the context resource in a **standard graph-based child variable**\r
+* **Represents**, which is a resource representing the variable **TODO**\r
+* **Type**, which returns a single type resource classifying the variable\r
+* **Role**, which tells whether the variable is a **child** or a **property** (TODO: could be deprecated)\r
+* **DATATYPE**, which returns the data type of a property variable. (TODO: should be HasDatatype)\r
+\r
+Other properties and the structure of the variable space is configured in the semantic graph or contributed by custom variable implementations.\r
+\r
+Variables can be located using an **URI**, which\r
+\r
+* Represents the path from **root variable** (Variables.getRootVariable) into the variable such that\r
+** **var/xx** represents a getChild(unescaped(xx)) query from var\r
+** **var#yy** represents a getProperty(unescaped(yy)) query from var\r
+** the escape function is bidirectional (URIStringUtils.escape and URIStringUtils.unescape)\r
+* Is an **identifier** (two variables with the same URI are the same in the sense of Java Object.equals)\r
+* Is a random access identifier (by Variables.getVariable())\r
+* Examples: \r
+** http://www.acme.org/Projects/MyProject/MyModel/Configuration/DiagramN/PI_X#PI_MASS_FLOW\r
+** http://www.acme.org/Projects/MyProject/MyModel/ExperimentConfiguration/RunName/DiagramN/PI_X#PI_MASS_FLOW#DATATYPE\r
+\r
+A common way of identifying a variable is by supplying a **base variable** and a **Relative Variable Identifier (RVI)**.\r
+\r
+* RVI represents the path from **base variable** into another variable\r
+* In textual RVI notation (Variable.browse())\r
+** **.** represents a getParent() query\r
+** **/xx** represents a getChild(unescaped(xx)) query\r
+** **#yy** represents a getProperty(unescaped(yy)) query\r
+* A literal RVI (Variable.getRVI(), RVI.resolve())\r
+** Does not need to depend on the names visible in the URI\r
+** Is based on e.g. resource ids\r
+** Survives export/import\r
+\r
+A **model** variable represents the root of a Simantics model\r
+* Model variables correspond directly to instances of SIMU.Model in the database\r
+** Variable and resource URIs are the same\r
+* For all variables under a model, the model variable can be obtained using Variables.getModel()\r
+\r
+A **context** variable under a model provides a view into a **state** of the model\r
+* The **Type** property of a context variable is inheried from L0.RVIContext\r
+* A RVI obtained from e.g. model configuration can be used to access similarly identified data from different model states\r
+** E.g. /DiagramX/ComponentY#PropertyZ can have different values in different contexts\r
+* The **configuration** context can be used to browse the structure and configuration values of the model\r
+* **Experiment run** contexts are used to monitor values from simulations or history\r
+\r
+The variable interface is bound to Simantics database **transactions**, but is not in any other way bound to the semantic data model, which allows variable implementations to represent arbitrary data models somehow related to Simantics models. All variable-based requests can be listened using standard Simantics database listening.\r
+\r
+Procedural children and variables are used with large data sets. E.g. query-based views can be exposed. Procedural properties also enable efficient slicing of arrays e.g. URI#Array_Property/0-99\r
+\r
+= General assertions in the Variable model =\r
+\r
+* All variables except the **root** have a parent\r
+* Let p be the parent of v. Then v#URI equals p#URI + '/'|'#' + escape(v#HasName)\r
+* Iff v1#URI equals v2#URI, then v1 and v2 are equal in Java Object.equals sense\r
+** Other identifications can be established by property values\r
+* A variable v2 equaling variable v can always be obtained by calling Variables.getVariable(v#URI)\r
+** The obtained variable **need not be the same object** but **can be**\r
+** Variables.getVariable can return also variables, which are not reachable by browsing (**TODO**)\r
+* All property variables have a value\r
+** No child variable has a value\r
+** The value of a property variable may be **null**\r
+** The value of **DATATYPE** property can be null for property variables i.e. property values can be arbitrary Java objects\r
+* Variable.getProperty returns all the variables returned from Variable.browseProperties\r
+** Variable.getProperty can return variables not returned by Variable.browseProperties\r
+* Variable.getChild returns all the variables returned from Variable.browseChildren\r
+** Variable.getChild can return variables not returned by Variable.browseChildren\r
+* A variable can be part of at most one **model**\r
+* A variable can be part of at most one **context**\r
+* All values can be accessed using either Variable.getValue or Variable.getInterface(Accessor.class)\r
+* All properties retrieved using Variable.browseProperties shall be available using Variable.getProperty\r
+* No variable can have a name that begins with one or more dots ('.') due to '.' being a reserved character for browsing the variable address space towards the parent. In other words names matching the pattern **"^\.+.*$"** are forbidden.\r
+\r
+# Standard properties\r
+\r
+## Connections\r
+\r
+* Connection point properties are classified with **http://www.simantics.org/Structural-1.0/ConnectionRelation**\r
+* The value of a connection point property is an object of class **org.simantics.structural2.variables.Connection**\r
+\r
+~~~\r
+\r
+public interface Connection {\r
+\r
+ Collection<Variable> getConnectionPoints(ReadGraph graph) throws DatabaseException;\r
+\r
+}\r
+\r
+~~~\r
+\r
+It is assumed that instances of **org.simantics.structural2.variables.Connection** have proper identities (equals/hashCode) based on flattened connections.\r
+\r
+The value of connection point properties can be **null**. This means that the connection point is not connected.\r
+\r
+## String editing operations\r
+\r
+* **HasDisplayValue** is a String-valued property, which is a formatted and unit-converted representation of the property value.\r
+* **expression** is a String-valued property, which is an SCL-formula used to compute the value of the property. If the property can be computed using an expression, this property is always available and returns **null** if an expression has not been defined.\r
+* **validator** is a **org.simantics.utils.strings.StringInputValidator**-valued property. The validator is used for checking values to be written into a property.\r
+\r
+~~~\r
+\r
+public interface StringInputProblem {\r
+\r
+ enum Severity {\r
+ Error, Warning\r
+ }\r
+\r
+ String getDescription();\r
+ int getBegin();\r
+ int getEnd();\r
+ Severity getSeverity();\r
+\r
+}\r
+\r
+public interface StringInputValidator {\r
+\r
+ Collection<StringInputProblem> validate(String input);\r
+\r
+}\r
+\r
+~~~\r
+\r
+* **valid** is a Boolean-valued property, which indicates whether the property contains a valid value.\r
+\r
+## Property properties\r
+\r
+* **required** is a Boolean-valued property, which indicates that the property should contain a valid value\r
+* **default** is a Boolean-valued property, which indicates that the property value is a default value\r
+* **readOnly** is a Boolean-valued property, which indicates that the property value can not be written\r
+\r
+## Complex datatypes\r
+\r
+* Record\r
+ * All named fields are '/name'\r
+ * Tuples are named after position e.g. '/11'\r
+* Union\r
+ * Union does not show in URI\r
+* Array\r
+ * Elements are named after position e.g. '/i-11'\r
+* Map\r
+ * Items are named after key\r
+\r
+# Standard graph based variable implementation\r
+\r
+The standard child and property variables are\r
+\r
+* org.simantics.db.layer0.variable.StandardGraphChildVariable\r
+* org.simantics.db.layer0.variable.StandardGraphPropertyVariable\r
+\r
+Their implementation is based on the following interfaces\r
+\r
+~~~\r
+\r
+package org.simantics.db.layer0.variable;\r
+\r
+public interface VariableMap {\r
+ Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException;\r
+ // Must not modify collection in any way not possible with put-method.\r
+ void getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException;\r
+}\r
+\r
+~~~\r
+\r
+~~~\r
+\r
+package org.simantics.db.layer0.variable;\r
+\r
+public interface ValueAccessor {\r
+ Object getValue(ReadGraph graph, Variable context) throws DatabaseException;\r
+ Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException;\r
+ void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException;\r
+ void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException;\r
+}\r
+\r
+~~~\r
+\r
+Implementations of the above interfaces can be bound to instances and types in the database via the following standard properties\r
+\r
+~~~\r
+\r
+L0.Entity\r
+ >-- L0.hasStandardResource ==> "Resource" <R L0.HasProperty : L0.FunctionalRelation\r
+ L0.HasDescription "The backend resource for standard graph-based Variables."\r
+ >-- L0.domainProperties ==> "VariableMap" <R L0.HasProperty : L0.FunctionalRelation\r
+ L0.HasDescription "Retruns a map of all domain properties of the entity."\r
+ >-- L0.domainChildren ==> "VariableMap" <R L0.HasProperty : L0.FunctionalRelation\r
+ L0.HasDescription "Retruns a map of all domain children of the entity."\r
+ >-- L0.valueAccessor ==> "ValueAccessor" <R L0.HasProperty : L0.FunctionalRelation\r
+ L0.HasDescription "Returns an interface for accessing the value."\r
+ @L0.assert L0.hasStandardResource\r
+ L0.Functions.hasStandardResource : L0.Function\r
+ @L0.assert L0.domainProperties L0.Functions.standardChildDomainProperties\r
+ @L0.assert L0.domainChildren L0.Functions.standardChildDomainChildren\r
+\r
+L0.Value\r
+ @L0.assert L0.domainProperties L0.Functions.standardPropertyDomainProperties\r
+ @L0.assert L0.domainChildren L0.Functions.standardPropertyDomainChildren\r
+ @L0.assert L0.valueAccessor L0.Functions.standardValueAccessor\r
+\r
+~~~\r
+\r
+The standard implementation is\r
+\r
+~~~\r
+\r
+@SCLValue(type = "ValueAccessor")\r
+public static ValueAccessor standardValueAccessor = new ValueAccessor() {\r
+\r
+ @Override\r
+ public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {\r
+ StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;\r
+ try {\r
+ ValueAccessor propertyAccessor = getPossiblePropertyValueAccessor(graph, variable);\r
+ if(propertyAccessor != null) return propertyAccessor.getValue(graph, context);\r
+ if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel);\r
+ }\r
+ if(variable.adapterClass != null) {\r
+ return graph.adaptRelated(variable.parentResource, variable.property, variable.adapterClass);\r
+ } else {\r
+ return graph.getRelatedValue2(variable.parentResource, variable.property, variable);\r
+ }\r
+ } catch (NoSingleResultException e) {\r
+ throw new MissingVariableValueException(variable.getPossibleURI(graph), e);\r
+ } catch (DoesNotContainValueException e) {\r
+ throw new MissingVariableValueException(variable.getPossibleURI(graph), e);\r
+ } catch (DatabaseException e) {\r
+ throw new MissingVariableValueException(variable.getPossibleURI(graph), e);\r
+ }\r
+ }\r
+ @Override\r
+ public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {\r
+ StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;\r
+ try {\r
+ ValueAccessor propertyAccessor = getPossiblePropertyValueAccessor(graph, variable);\r
+ if(propertyAccessor != null) return propertyAccessor.getValue(graph, context, binding);\r
+ if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding);\r
+ }\r
+ if(variable.adapterClass != null) {\r
+ return graph.adaptRelated(variable.parentResource, variable.property, variable.adapterClass);\r
+ } else {\r
+ return graph.getRelatedValue2(variable.parentResource, variable.property, variable, binding);\r
+ }\r
+ } catch (NoSingleResultException e) {\r
+ throw new MissingVariableValueException(variable.getPossibleURI(graph));\r
+ } catch (DoesNotContainValueException e) {\r
+ throw new MissingVariableValueException(variable.getPossibleURI(graph));\r
+ } catch (DatabaseException e) {\r
+ throw new MissingVariableValueException(variable.getPossibleURI(graph));\r
+ }\r
+ }\r
+ @Override\r
+ public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {\r
+ StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;\r
+ ValueAccessor propertyAccessor = getPossiblePropertyValueAccessor(graph, variable);\r
+ if(propertyAccessor != null) {\r
+ propertyAccessor.setValue(graph, context, value);\r
+ return;\r
+ }\r
+ Function4<WriteGraph, Variable, Object, Object, String> modifier = context.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER);\r
+ if(modifier == null) modifier = VariableUtils.defaultInputModifier;\r
+ try {\r
+ modifier.apply(graph, context, value, Bindings.getBinding(value.getClass()));\r
+ } catch (BindingConstructionException e) {\r
+ throw new DatabaseException(e);\r
+ }\r
+ }\r
+ @Override\r
+ public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {\r
+ StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;\r
+ ValueAccessor propertyAccessor = getPossiblePropertyValueAccessor(graph, variable);\r
+ if(propertyAccessor != null) {\r
+ propertyAccessor.setValue(graph, context, value, binding);\r
+ return;\r
+ }\r
+ Function4<WriteGraph, Variable, Object, Object, String> modifier = context.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER);\r
+ if(modifier == null) modifier = VariableUtils.defaultInputModifier;\r
+ modifier.apply(graph, context, value, binding);\r
+ }\r
+};\r
+\r
+@SCLValue(type = "VariableMap")\r
+public static VariableMap standardChildDomainProperties = new VariableMap() {\r
+\r
+ @Override\r
+ public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
+ final StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
+ return getPossiblePropertyFromContext(graph, variable, variable.resource, name);\r
+ }\r
+ @Override\r
+ public void getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
+ StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
+ collectPropertiesFromContext(graph, variable, variable.resource, map);\r
+ }\r
+\r
+};\r
+\r
+@SCLValue(type = "VariableMap")\r
+public static VariableMap standardPropertyDomainProperties = new VariableMap() {\r
+\r
+ @Override\r
+ public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
+ StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;\r
+ Resource literal = graph.getPossibleObject(variable.parentResource, variable.property);\r
+ if(literal != null) {\r
+ Variable result = getPossiblePropertyFromContext(graph, variable, literal, name);\r
+ if(result != null) return result;\r
+ }\r
+ return getPossiblePropertyFromContext(graph, variable, variable.property, name);\r
+ }\r
+ @Override\r
+ public void getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
+ StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;\r
+ collectPropertiesFromContext(graph, variable, variable.property, map);\r
+ Resource literal = graph.getPossibleObject(variable.parentResource, variable.property);\r
+ if(literal != null) collectPropertiesFromContext(graph, variable, literal, map);\r
+ }\r
+\r
+};\r
+\r
+@SCLValue(type = "VariableMap")\r
+public static VariableMap standardChildDomainChildren = new VariableMap() {\r
+\r
+ @Override\r
+ public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
+ StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
+ Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(variable.resource));\r
+ Resource child = children.get(name);\r
+ if(child == null) return null;\r
+ return graph.getPossibleContextualAdapter(child, variable, Variable.class, Variable.class);\r
+ }\r
+ @Override\r
+ public void getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
+ StandardGraphChildVariable variable = (StandardGraphChildVariable)context;\r
+ for(Map.Entry<String, Resource> entry : graph.syncRequest(new UnescapedChildMapOfResource(variable.resource)).entrySet()) {\r
+ String name = entry.getKey();\r
+ Resource child = entry.getValue();\r
+ Variable var = graph.getPossibleContextualAdapter(child, variable, Variable.class, Variable.class);\r
+ if(var != null) {\r
+ map.put(name, var);\r
+ } else {\r
+ System.err.println("No adapter for " + child + " in " + variable.getURI(graph));\r
+ }\r
+ }\r
+ }\r
+\r
+};\r
+\r
+@SCLValue(type = "VariableMap")\r
+public static VariableMap standardPropertyDomainChildren = new VariableMap() {\r
+\r
+ @Override\r
+ public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
+ StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;\r
+ Datatype dt = variable.getDatatype(graph);\r
+ if (dt instanceof ArrayType) {\r
+ ChildReference ref = getPossibleIndexReference(name);\r
+ if (ref != null)\r
+ return new SubliteralPropertyVariable(variable, ref);\r
+ }\r
+ return null;\r
+ }\r
+ @Override\r
+ public void getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
+ }\r
+\r
+};\r
+\r
+~~~\r
+\r
+## Informally\r
+\r
+Standard child modelling assumes a context resource res.\r
+\r
+* childResource : where (res, L0.ConsistsOf, childResource)\r
+* childVariable = graph.adaptContextual(childResource, this, Variable.class, Variable.class)\r
+\r
+Standard property modelling assumes a context resource res.\r
+\r
+* (predicate, object) : where (res, predicate, object) and (predicate <R L0.HasProperty)\r
+* childProperty = graph.adaptContextual(object, ModelledVariablePropertyDescriptor(this, predicate), Variable.class)\r
+\r
+For property variables there are two context resources available, the associated value and the predicate. Properties are found from the value context first and then from the predicate context.\r
+\r
+The graph.adaptContextual step is an extension point for defining custom variable implementations contributed using the adapter (adapters.xml) mechanism.\r
+\r
+# Frequent cases\r
+\r
+1. Given variable v, obtain model (Resource)\r
+ call Variables.getModel(graph, v)\r
+2. Given variable v, obtain context (Variable)\r
+ call Variables.getContext(graph, v)\r
+3. Given Variable URI, obtain Variable\r
+ call Variables.getVariable(graph, uri)\r
+4. Obtain string representation for value of Variable v\r
+ obtain value of v#HasDisplayValue\r
+\r
+to be continued...\r
+\r
+# Open issues\r
+\r
+## Generic simulator support in Variable ==\r
+\r
+Current hypothesis is that we extends standard graph based implementation by a special interface, which serves the simulator (or other) data. The standard implementation then combines data from graph and simulator. The special interface is designed such that is supports custom synchronization and lazy operation and can also be directly utilized in remote simulators.\r
+\r
+## Variable syntax in SCL\r
+\r
+* Implement variable interface methods as normal functions\r
+ * Example: <code>browse entrypoint "./Out#sdf"</code>\r
+* Use . and #-for browsing\r
+ * How to browse parent? Explicit function\r
+ * Example: <code>(parent entrypoint).Out#sdf</code>\r
+ * Special operator for parents (binds stronger than . or #):\r
+ * Example: <code>!entrypoint.Out#sdf</code>\r
+* Resolve entrypoints in the context\r
+ * Example: <code>Out#sdf</code>\r
+ * Local variable definitions may shadow context\r
+\r
+## Experiment modelling\r
+\r
+The modelling of experiment run contexts and the value types of properties in states is still underway.\r
+\r
+# Refactoring\r
+\r
+* <strike>add Collection<Variable> browseProperties(ReadGraph graph, String classification) throws DatabaseException;</strike>\r
+* add standard property **classifications**, which returns a set of strings\r
+* <strike>deprecate browseChildren, browseProperties => add get</strike>\r
--- /dev/null
+# Intro\r
+\r
+The Simantics database client allows for defining memory-based and disk-based graph fragments which are applied on top of the server-based semantic graph.\r
+\r
+A reading user perceives the combined model and the virtual graph information can be specifically queried if necessary.\r
+\r
+A modifying user needs to specify in which virtual graph the modifications are made.\r
+\r
+Virtual graphs are manipulated via the following interfaces\r
+\r
+* **org.simantics.db.service.VirtualGraphSupport**, for management\r
+* **org.simantics.db.request.WriteTraits**, for identifying the graph to write into\r
+\r
+## Specification\r
+\r
+A write request has a single graph into which it writes. This is determined by *WriteTraits* and usually as a parameter to *WriteRequest*. If null is provided, the client applies modifications into the persistent graph. The following rules apply:\r
+\r
+* New resources are created into the given virtual graph\r
+* Claim statements are added into the given virtual graph\r
+* Value changes are applied into the given virtual graph\r
+* When the virtual graph provided to the WriteRequest is:\r
+** **null**:\r
+*** For denied statements the location of the statement is determined and the statement is removed from that virtual graph. If the denied statement is not a part of any virtual graph, it is removed from the persistent graph.\r
+** **non-null**:\r
+*** Statements are only removed from the virtual graph specified for the write request\r
+\r
+The user can perform modifications into multiple virtual graphs within a single transaction. This is accomplished by issuing a new synchronous modification (WriteGraph.sync) into a new virtual graph.\r
+\r
+## Examples\r
+\r
+The following code examples show in practice how to write into virtual graphs, both memory- and disk-based. Writing to several virtual graphs within the same write transaction is also demonstrated.\r
+\r
+~~~\r
+package org.simantics.db.tests.api.support.virtualGraphSupport;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.RequestProcessor;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.VirtualGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.common.request.WriteResultRequest;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.service.VirtualGraphSupport;\r
+import org.simantics.layer0.Layer0;\r
+\r
+public class VirtualGraphExample {\r
+\r
+ public Resource createLibrary(RequestProcessor processor, VirtualGraph vg, final String libraryName)\r
+ throws DatabaseException {\r
+ return processor.syncRequest(new WriteResultRequest<Resource>(vg) {\r
+ @Override\r
+ public Resource perform(WriteGraph graph) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ Resource r = graph.newResource();\r
+ graph.claim(r, L0.InstanceOf, null, L0.Library);\r
+ graph.claimLiteral(r, L0.HasName, libraryName);\r
+ return r;\r
+ }\r
+ });\r
+ }\r
+\r
+ public void testVirtualGraphs(Session session) throws DatabaseException {\r
+ VirtualGraphSupport vgSupport = session.getService(VirtualGraphSupport.class);\r
+ VirtualGraph memory = vgSupport.getMemoryPersistent("memory");\r
+ VirtualGraph workspace = vgSupport.getWorkspacePersistent("workspace");\r
+ // NOTICE: resource are created in difference virtual graphs in separate\r
+ // transactions through Session.syncRequest.\r
+ Resource memResource = createLibrary(session, memory, "memory");\r
+ Resource workspaceResource = createLibrary(session, workspace, "workspace");\r
+ printVirtualGraphs(session);\r
+ }\r
+\r
+ public void testMultipleVirtualGraphsInSameTransaction(Session session) throws DatabaseException {\r
+ final VirtualGraphSupport vgSupport = session.getService(VirtualGraphSupport.class);\r
+ session.syncRequest(new WriteRequest() {\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ VirtualGraph memory = vgSupport.getMemoryPersistent("memory");\r
+ VirtualGraph workspace = vgSupport.getWorkspacePersistent("workspace");\r
+ // NOTICE: resource are created in different virtual graphs in\r
+ // the same transaction through WriteGraph.syncRequest\r
+ Resource memResource = createLibrary(graph, memory, "memory");\r
+ Resource workspaceResource = createLibrary(graph, workspace, "workspace");\r
+ }\r
+ });\r
+ printVirtualGraphs(session);\r
+ }\r
+\r
+ public void printVirtualGraphs(Session session) throws DatabaseException {\r
+ session.syncRequest(new ReadRequest() {\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ VirtualGraphSupport vgSupport = graph.getService(VirtualGraphSupport.class);\r
+ for (VirtualGraph vg : vgSupport.listGraphs()) {\r
+ for (Statement stm : vgSupport.listStatements(vg)) {\r
+ System.out.println("Statement: " + NameUtils.toString(graph, stm));\r
+ }\r
+ for (Resource r : vgSupport.listValues(vg)) {\r
+ System.out.println("Literal value: " + graph.getValue(r));\r
+ }\r
+ }\r
+ }\r
+ });\r
+ }\r
+\r
+}\r
+~~~\r
+\r
+## Debugging\r
+\r
+The standard Simantics Graph Debugger view shows for every statement which virtual graph it belongs to. This information is visible on the *Graph* column of the statement table. The Graph column will show:\r
+;DB: when the statement is in the persistent graph\r
+;'name' (W): when the statement is in a named workspace-persistent virtual graph\r
+;'name' (M): when the statement is in a named memory-persistent (transient) virtual graph\r
+\r
+[[Image:GraphDebuggerVG.png|frame|center|Graph debugger example with statements in virtual graphs.]]\r
--- /dev/null
+# Simantics Developer Documentation\r
+\r
+Simantics is a software platform for modelling and simulation. The system has client-server architecture with a semantic ontology-based modelling database and Eclipse framework -based client software with plug-in interface. The Simantics platform and many of its components are open source under Eclipse Public License (EPL).\r
+\r
+The philosophy of the Simantics platform is to offer an open, high level application platform on which different computational tools can be easily integrated to form a common environment for modelling and simulation. The platform includes several modelling tools, so-called editors, for e.g. 2D graph-like hierarchical model composition and semantic graph browsing.\r
+\r
+One of the biggest innovations in the Simantics platform is the semantic modelling approach itself and high-level ontology tools. The semantic database, i.e. triplestore, on the server side enables high performance data management and arbitrary mappings of data. This enables e.g. efficient mapping of simulation and measurement data to the model configuration and its visualisation.\r
+\r
+The Simantics development and maintenance process is built to be solid and scalable from the very beginning. The objective is to aim far to the future what comes to requirements for scalability, usability, and reliability.\r
+\r
+This Simantics Developer Documentation is targeted to programmers and software developers developing either the platform itself or additional plug-ins to be used with or on the platform. The Simantics End User Documentation complements to documentation for the Simantics platform offering overview and detailed information about the platform from the user's point of view. The [Simantics website](https://www.simantics.org/) is the source of information for the Simantics project and related subjects.\r
--- /dev/null
+Simantics binary container format is a format for storing binary encoded data to file system.\r
+\r
+~~~\r
+type DataContainer = {\r
+ format : String,\r
+ version : Integer,\r
+ metadata : Map(String, Variant),\r
+ content : Variant\r
+}\r
+~~~\r
+\r
+In addition to the actual content data that is stored as a Variant, a file contains a format name that tells how the data is used: for example "aprosModel", "aprosSymbol" and a version number. Applications use format name to decide if the file can be used for the operation the user has requested and version number to choose how to handle the data.\r
+\r
+Version number is increased by one every time the data type of the content or the semantics of the data (how it should be handled in the application) is changed.\r
--- /dev/null
+# Introduction\r
+\r
+The *org.simantics.graph* feature provides a textual graph database source editing environment that integrates into the Eclipse IDE.\r
+\r
+The feature adds a new project nature and builder for Java/Plug-in projects to support development of `.pgraph` *partial graph* source files. The environment will compile all partial graphs with in a project into a single *[Transferable Graph](TransferableGraph.md)* `/graph.tg`. Simantics applications will then be able to integrate this transferable graph into handled databases.\r
+\r
+The environment also allows you to add the graph compilation nature to any project from the project's context menu *Configure/Add graph compilation*.\r
+\r
+# Install\r
+\r
+The graph development environment is distributed using an update site at [http://www.simantics.org/update/utils](http://www.simantics.org/update/utils).\r
--- /dev/null
+Textual graph format is used to write ontologies in Simantics platform. [Graph Compiler](GraphCompiler.md) translates textual format to binary [Transferable graphs](TransferableGraph.md) that can be then imported to Simantics database.\r
+\r
+## Syntax\r
+\r
+### Indentation\r
+\r
+The graph format is indentation based. The amount of indentation can be freely chosen, but it has to be consistent with the previous lines. The lines can be indendented only with spaces. Tabulators are not allowed.\r
+\r
+Both C and C++ style comments are allowed. If a C style comment begins a line, there must not be anything else in the line after the comment, otherwise the amount of indentation would be then unclear. Text in parenthesis (), [] and {} can be freely indented.\r
+\r
+### Statements\r
+\r
+A graph file describes a collection of statements. One statement is written as:\r
+\r
+ Subject Predicate Object\r
+\r
+and represented graphically as\r
+\r
+![Subject Predicate Object](Images/SubPreObj.png)\r
+\r
+Statements with the same subject can be written in the same line\r
+\r
+ Subject Predicate1 Object1 Predicate2 Object2 Predicate3 Object3\r
+\r
+or with multiple indented lines\r
+\r
+~~~\r
+ Subject\r
+ Predicate1 Object1\r
+ Predicate2 Object2\r
+ Predicate3 Object3\r
+~~~\r
+\r
+These forms can also be combined\r
+\r
+~~~\r
+ Subject Predicate1 Object1 Predicate2 Object2\r
+ Predicate3 Object3\r
+ Predicate4 Object4\r
+~~~\r
+\r
+Statements with the same subject and predicate can be abbreviated as\r
+\r
+~~~\r
+ Subject\r
+ Predicate\r
+ Object1\r
+ Object2\r
+ Object3\r
+~~~\r
+\r
+In this case, there must be no objects in the same line with the predicate.\r
+\r
+Statements concerning the object of another statement can be written after the object if the object is not in the same line with the original subject. The following texts describe the same graph:\r
+\r
+![Subject Predicate Object Chain](Images/SubPreObj_chain_01.png)\r
+\r
+~~~\r
+Subject Predicate1 Object1\r
+Object1 Predicate2 Object2\r
+\r
+Subject\r
+ Predicate1 Object1 Predicate2 Object2\r
+\r
+Subject\r
+ Predicate1 Object1\r
+ Predicate2 Object2\r
+\r
+Subject\r
+ Predicate1\r
+ Object1 Predicate2 Object2 \r
+\r
+Subject\r
+ Predicate1\r
+ Object1\r
+ Predicate2 Object2\r
+\r
+Subject\r
+ Predicate1\r
+ Object1\r
+ Predicate2\r
+ Object2\r
+~~~\r
+\r
+### Resources\r
+\r
+Subject, predicate, and object of a statement are all resources. Predicates and other resources are handled little differently. A resource can be in one of the following forms:\r
+* Identifier\r
+* URI\r
+* Reference to a child of another resource\r
+* Literal value (not allowed as a predicate)\r
+* Data type (not allowed as a predicate)\r
+* A special relation: =, <T, <R, : (allowed only as a predicate)\r
+\r
+Identifier must begin with a letter or '_' and continue with letters, numbers and '_' characters. Single underscore _ is a special identifier that denotes a fresh resource: Every _ refers to a different resources.\r
+\r
+URI is enclosed in <>-characters and must begin with "http:". For example\r
+`<http://www.simantics.org/Layer0-1.0/InstanceOf>`.\r
+\r
+The syntax of literal values and data types is specified in [[Databoard Specification#Value Text Notation]]. Variants and tagged values (of some union type) must be enclosed in parenthesis. A data type must be prefixed with $ and union types and array types must be enclosed in parenthesis.\r
+\r
+References are used to refer URIs: If identifier A referes to <nowiki><http://somedomain/A></nowiki>, then A.Foo referes to <nowiki><http://somedomain/A/Foo></nowiki>. If URI contains non-alphanumerical characters, the name can be enclosed in double quotes. For example A."Cul-de-sac" refers to <nowiki><http://somedomain/A/Cul-de-sac></nowiki>.\r
+\r
+Special relations are abbreviations of some Layer0 relations:\r
+{|\r
+|-\r
+|width="40px" align="center"| =\r
+| <nowiki>http://www.simantics.org/Layer0-1.0/Equals</nowiki>\r
+|-\r
+|width="40px" align="center"| <T\r
+| <nowiki>http://www.simantics.org/Layer0-1.0/Inherits</nowiki>\r
+|-\r
+|width="40px" align="center"| <R\r
+| <nowiki>http://www.simantics.org/Layer0-1.0/SubrelationOf</nowiki>\r
+|-\r
+|width="40px" align="center"| :\r
+| <nowiki>http://www.simantics.org/Layer0-1.0/InstanceOf</nowiki>\r
+|-\r
+|width="40px" align="center"| >--\r
+| <nowiki>http://www.simantics.org/Layer0-1.0/IsDomainOf</nowiki>\r
+|-\r
+|width="40px" align="center"| <--\r
+| <nowiki>http://www.simantics.org/Layer0-1.0/HasDomain</nowiki>\r
+|-\r
+|width="40px" align="center"| -->\r
+| <nowiki>http://www.simantics.org/Layer0-1.0/HasRange</nowiki>\r
+|-\r
+|width="40px" align="center"| ==>\r
+| <nowiki>http://www.simantics.org/Layer0-1.0/RequiresValueType</nowiki>\r
+|}\r
+\r
+### Templates\r
+\r
+A template is a parametrized graph that can be defined and instantiated.\r
+\r
+A template is defines as follows:\r
+\r
+~~~\r
+ <name of the template> : L0.Template\r
+ @template <parameters>\r
+ <template body>\r
+~~~\r
+\r
+for example\r
+\r
+~~~\r
+ L0.assert : L0.Template\r
+ @template %type %predicate %object\r
+ %type\r
+ L0.Asserts _ : L0.Assertion\r
+ L0.HasPredicate %predicate\r
+ L0.HasObject %object\r
+~~~\r
+\r
+The template body is written in normal graph notation that can be refer to the parameters.\r
+\r
+A templates is applied as follows:\r
+\r
+ @<name of the template> <parameter1> ... <parameterN>\r
+ <parameterN+1> ...\r
+ ...\r
+ <parameterN+2> ...\r
+ ...\r
+ ...\r
+\r
+For example\r
+\r
+ My.Type <T L0.Entity\r
+ @L0.assert My.HasTransformation\r
+ 4.0 : My.Transformation\r
+\r
+## Completion rules\r
+\r
+A textual graph is flattened to a set of raw statements in a straightforward way. After that some rules are applied that add statements to the graph.\r
+\r
+### Merging equal resources\r
+\r
+All resources that have the relation `<http://www.simantics.org/Layer0-1.0/Equals>` (=) between them are merged, i.e their statements are combined. This can be used to give shorthand references to resources:\r
+\r
+~~~\r
+L0 = <http://www.simantics.org/Layer0-1.0>\r
+Foo <T L0.Entity\r
+~~~\r
+\r
+### Typing literals\r
+\r
+The data type of a literal must be specified either with HasDataType statement or by instantiating a type that asserts this kind of statement:\r
+\r
+ 1 : L0.Literal\r
+ L0.HasDataType @Integer\r
+\r
+ 1 : L0.Integer\r
+\r
+In order to make writing graphs easier, the InstanceOf statement of a literal is derived from the value, if it is not explicitly specified. The following literal types defined in Layer0 are supported:\r
+* Boolean\r
+* Integer\r
+* Double\r
+* String\r
+* BooleanArray\r
+* IntegerArray\r
+* DoubleArray\r
+* StringArray\r
+\r
+### Inverse relations\r
+\r
+A default inverse relation is created for a relation whose superrelation has an inverse. Also superrelations are added to inverses automatically based on the superrelations of the relation.\r
+\r
+Relations will thus have inverses if:\r
+* an inverse is explicitly defined for a relation:\r
+\r
+ ONTOLOGY.SymmetricRelation <R L0.IsWeaklyRelatedTo\r
+ @L0.symmetric\r
+ ONTOLOGY.RelationWithExplicitInverse <R L0.IsRelatedTo\r
+ L0.InverseOf ONTOLOGY.RelationWithExplicitInverse.Inverse <R L0.IsRelatedTo\r
+\r
+* a relation is inherited from another relation that has an inverse, in which case an inverse relation is generated if one is not defined.\r
+\r
+ ONTOLOGY.RelationWithGeneratedInverse <R L0.IsComposedOf\r
+ // ONTOLOGY.RelationWithGeneratedInverse.Inverse will be generated\r
--- /dev/null
+Transferable Graph (.tg) is a statement container file. Transferable Graphs can be exported from and imported into graph databases.\r
+\r
+The format uses [Binary Container Format](BinaryContainerFormat.md) where content is encoded with the following datatype according to the [Databoard Specification](../Data/Databoard.md):\r
+\r
+## Format (graph:1)\r
+\r
+~~~\r
+ type TransferableGraph1 = {\r
+ resourceCount : Integer,\r
+ extensions : Map(String, Variant),\r
+ identities : Identity[], \r
+ statements : Integer[],\r
+ values : Value[]\r
+ }\r
+\r
+ type Identity {\r
+ resource : Integer,\r
+ definition : IdentityDefinition\r
+ }\r
+\r
+ type IdentityDefinition =\r
+ | Root { name : String, type : String }\r
+ | External { parent : Resource, name : String } \r
+ | Optional { parent : Resource, name : String }\r
+ | Internal { parent : Resource, name : String }\r
+\r
+ type Value = {\r
+ resource : Integer,\r
+ value : Variant\r
+ }\r
+~~~\r
+\r
+Each resource in a transferable graph is referred with a 32-bit integer beginning with zero.\r
+\r
+| Field | Description |\r
+|-------|-------------|\r
+|resourceCount|Tells how many resources are used in the file. Some resources may already exist in the database, some will be new.|\r
+|extensions|Any additional data represented as variants and identified by string keys. Allows transferable graph contents extensibility without format changes. Extensions will most probably contain data that is somehow related to statement and value data that comes after it. Therefore it is better for streaming input to have it available earlier than the data itself.|\r
+|identities|Tells how to find the resources that should already exist in the database. Also the new resources with URI are given an identity so that it easier to refer to them when the graphs are compiled separately. The identities have to be ordered so that if the identity refers to another resource, its identity is already given.|\r
+|statements|Contains all new statements that the transferable graph defines. The length of the array is 4*resourceCount. The array has for every statement its subject, predicate, inverse of the predicate and object in this order. If the statement does not have an inverse (that is different from itself), the inverse is -1.|\r
+|values|Assigns values to all literals in the transferable graph. Literals are represented as variants.|\r
+\r
+An identity can be of one of the following types:\r
+* `Root` defines a resource as a root. If `name` is "", the resource is the root library of the database. Other roots are interpreted in application specific ways.\r
+* `External` tells that a resource is a child of some other resource and should already exist in the database.\r
+* `Optional` tells that a resource is a child of some other resource. It may exist or not exist already in the database. In the latter case, it is created.\r
+* `Internal` tells that a resource is a child of some other resource. It may not yet exist in the database for the import to be successful.\r
+\r
+## Conversions\r
+\r
+Conversion from version 0 to version graph:1. [[File:tg0_tg1.jar]] Usage:\r
+\r
+ java -jar tg0_tg1.jar graph input.tg output.tg\r
+\r
+The second argument is the name of the target file format.\r
--- /dev/null
+This document addresses the issue of how simantics application migrates from one version to the next. The scope includes software and ontology development.\r
+\r
+## Ontology Migration\r
+An ontology is a compilation of shared *concepts* (=types, relations and instances).\r
+\r
+ http://www.simantics.org/Layer0-1.0\r
+ http://www.simantics.org/Layer0-1.0/ConsistOf\r
+ http://www.simantics.org/Layer0-1.0/Library\r
+\r
+Ontologies are versioned according to the following scheme\r
+\r
+ <Ontology URI>-<major version>.<minor version>\r
+\r
+For example\r
+\r
+ http://www.simantics.org/Layer0-1.0\r
+\r
+All shared concepts contained in the ontology are accordingly versioned along with the ontology and the version number is visible in the URI. For ontological concepts we define\r
+\r
+* **versioned URI** as the proper URI of the resource e.g. `http://www.simantics.org/Layer0-1.0/ConsistsOf`\r
+* **unversioned URI** where version information is omitted e.g. `http://www.simantics.org/Layer0-0.0/ConsistsOf`\r
+\r
+Ontologies are deployed as OSGi bundles. Declarations in Simantics software may use the unversioned URI to refer to concepts in the *latest* version on an ontology (or the version found from OSGi dependencies). An utility class for converting between **versioned URI** and **unversioned URI** is defined in class **org.simantics.scl.reflection.OntologyVersions**.\r
+\r
+Additionally we define\r
+\r
+* **working ontology** as an ontology bundle which contains the **latest** version of the ontology e.g. *org.simantics.simulation.ontology*\r
+* **released ontology** as an ontology bundle which is frozen, renamed and never again changed e.g. *org.simantics.simulation.ontology-1.1*\r
+\r
+The following simple rules for ontology development are defined to enable version migration\r
+\r
+### Modelling rules\r
+\r
+1. All ontology versions shall be completely self-contained. All concepts are declared in all versions of an ontology.\r
+2. There shall be exactly one ontology (L0.Ontology) defined in each ontology bundle.\r
+3. The **Bundle-Name** of an ontology shall be the unversioned URI of the ontology without the '-0.0' suffix e.g. <nowiki>http://www.simantics.org/Simulation</nowiki>\r
+4. The first two digits of the **Bundle-Version** of an ontology shall be the ontology version as specified in the ontology URI e.g. '1.2'\r
+5. The **Bundle-SymbolicName** (bundle id) of a working ontology is unchanged when versions grow (e.g. org.simantics.simulation.ontology)\r
+6. The **Bundle-SymbolicName** (bundle id) of a frozen ontology is a version-dependent derivative of the id from the working ontology (e.g. org.simantics.simulation.ontology-1.1)\r
+\r
+## Model Migration\r
+\r
+A project in a database contains models of different versions created with different versions of software features.\r
+\r
+The database can host multiple versions of ontologies which enables old models to exist and to be imported in the database. A typical software feature can only manipulate models defined with the latest versions of some ontologies.\r
+\r
+Software features can make model migration from models created with previous versions of the software. Each model is *associated in the database with a single software feature version*, which then can be used to determine the actions needed for migrating models to the latest ontological definitions. The version modelling is defined in **org.simantics.softwareconfiguration.ontology**.\r
+\r
+The user can browse the old and new models contained in the database and perform model migration at will.\r
+\r
+## Making software releases\r
+\r
+A released Simantics feature uses a set of ontologies with specified version numbers. All models associated with a specific software version need access to these ontology versions even after the ontologies have evolved. Thus it is necessary to release and freeze all versions of used ontologies whenever a software is released. Thus the procedure for making a software release includes\r
+\r
+### The release process\r
+\r
+* **Before the build**\r
+ 1. Make usual tagging and branching of all released plugins in Subversion\r
+* **Right after the build**\r
+ 1. For all working ontologies which do not correspond to a frozen version : freeze ontology plugin and store as a tag\r
+ 2. Increment the software version number of models\r
+* **During modelling when ontology is first modified** (before this the working ontology was exactly some frozen ontology)\r
+ 1. Increment ontology version number. (Include the corresponding frozen ontology into product dependencies to enable migration).\r
--- /dev/null
+Simantics Generic File Import is a utility service that enables [Eclipse's Dropins](http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fmisc%2Fp2_dropins_format.html)-like functionality. The directory resides inside `~/workspace/.metadata/plugins/org.simantics.fileimport/dropins` and it is not watched by default. There are two ways to start the watchservice:\r
+\r
+1. Call directly in Java `FileImportDropins.watchDropinsFolder()`\r
+2. Use SCL function `watchDropinsFolder` from `"Dropins/Core"`\r
+\r
+## Creating own File importer\r
+\r
+To create own File importer it is usually enough to extend the abstract class `SimanticsResourceFileImport` and implement the two methods:\r
+\r
+ /**\r
+ * Returns a key-value map for file extensions this importer can handle\r
+ *\r
+ * @return Map<String, String> allowed extensions this service can handle. Key is the extension e.g. <code>.sharedLibrary</code> and the value is the description of the extension\r
+ */\r
+ Map<String, String> allowedExtensionsWithFilters();\r
+\r
+ /*\r
+ * Performs the import for the given file\r
+ *\r
+ * @param parent Resource parent of the imported entity in Simantics database\r
+ * @param file Path file location of file\r
+ * @return Optional Resource of the imported entity in Simantics database\r
+ * @throws Exception\r
+ */\r
+ public abstract Optional<Resource> perform(Resource parent, Path file) throws Exception;\r
+\r
+An example of such a class for importing FMU-files to Simantics workbench would be following:\r
+\r
+~~~\r
+public class FMIFileImport extends SimanticsResourceFileImport {\r
+\r
+ private static final Map<String, String> EXTENSIONS_FILTERS = Collections.singletonMap("*.fmu",\r
+ "Functional Mock-up Unit (*.fmu)");\r
+\r
+ @Override\r
+ public Optional<Resource> perform(Resource parent, Path file) throws IOException{\r
+ try {\r
+ Resource model = FMIStudioSCL.createFMIModel(parent, file);\r
+ return Optional.of(model);\r
+ } catch (FMILException | DatabaseException e) {\r
+ e.printStackTrace();\r
+ return Optional.empty();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Map<String, String> allowedExtensionsWithFilters() {\r
+ return EXTENSIONS_FILTERS;\r
+ }\r
+\r
+}\r
+~~~\r
+\r
+It is important to create the component for defining declarative service. To do this right click the same plugin where the implmentation is and click New -> Other -> Plug-in Development -> Component Definition.\r
+\r
+Give the name for the XML file and and browse to the implementing class You just created.\r
+\r
+An example of XML-file is:\r
+\r
+<pre>\r
+<?xml version="1.0" encoding="UTF-8"?>\r
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.simantics.fmi.studio.fileimport">\r
+ <implementation class="org.simantics.fmi.studio.fileimport.FMIFileImport"/>\r
+ <service>\r
+ <provide interface="org.simantics.fileimport.IGenericFileImport"/>\r
+ </service>\r
+</scr:component>\r
+</pre>\r
+\r
+## FileImportService utility class\r
+\r
+The class `org.simantics.fileimport.FileImportService` contains utility methods for e.g. listing all current services and performing file imports:\r
+\r
+~~~\r
+ /**\r
+ * Lists all supported file extensions which have a registered service for handling the import\r
+ *\r
+ * @return Map containing the extension and the description of the extension in that order\r
+ */\r
+ public static Map<String, String> supportedExtensionsWithFilters();\r
+\r
+ /**\r
+ * Method that performs the import of the given file. This method is called when e.g. {@link FileImportDropins} watcher detects {@link java.nio.file.StandardWatchEventKinds.ENTRY_CREATE} operation\r
+ *\r
+ * @param file Path file to be imported\r
+ * @param callback Optional callback which can be used to catch Throwables thrown in the import process\r
+ */\r
+ public static void performFileImport(Path file, Optional<Consumer<Throwable>> callback);\r
+~~~\r
--- /dev/null
+For uniform logging in Simantics Platform [ The Simple Logging Facade for Java](http://www.slf4j.org/) (`org.slf4j.api`) and [Logback Project](http://logback.qos.ch/) (`ch.qos.logback.classic`) is included in Simantics SDK. To use the SLF4J logging API just include the following bundle in your own plugin's `MANIFEST.MF` dependencies:\r
+\r
+ Require-Bundle: ..,\r
+ org.slf4j.api\r
+\r
+An example usage of logging inside your own java code is presented below:\r
+\r
+~~~\r
+ 1: import org.slf4j.Logger;\r
+ 2: import org.slf4j.LoggerFactory;\r
+ 3:\r
+ 4: public class Wombat {\r
+ 5: \r
+ 6: private static final Logger LOGGER = LoggerFactory.getLogger(Wombat.class);\r
+ 7: private Integer t;\r
+ 8: private Integer oldT;\r
+ 9:\r
+10: public void setTemperature(Integer temperature) {\r
+11: \r
+12: oldT = t; \r
+13: t = temperature;\r
+14:\r
+15: LOGGER.debug("Temperature set to {}. Old temperature was {}.", t, oldT);\r
+16:\r
+17: if(temperature.intValue() > 50) {\r
+18: LOGGER.info("Temperature has risen above 50 degrees.");\r
+19: }\r
+20: }\r
+21: }\r
+~~~\r
+\r
+The SLF4J Manual can be found here: http://www.slf4j.org/manual.html\r
+\r
+## Configuring Logback\r
+\r
+By default bundle `org.simantics.logback.configuration` contains the `logback.xml` configuration file in which the logging format and different appenders are defined. By default it looks like this:\r
+\r
+~~~\r
+<?xml version="1.0" encoding="UTF-8"?>\r
+<configuration>\r
+\r
+ <appender name="console" class="ch.qos.logback.core.ConsoleAppender">\r
+ <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->\r
+ <encoder>\r
+ <pattern>%-5p [%d] %c: %m%n%rEx</pattern>\r
+ </encoder>\r
+ </appender>\r
+\r
+ <appender name="async-console" class="ch.qos.logback.classic.AsyncAppender">\r
+ <appender-ref ref="console" />\r
+ </appender>\r
+\r
+ <root level="debug">\r
+ <appender-ref ref="async-console" />\r
+ </root>\r
+</configuration>\r
+~~~\r
+\r
+This configuration creates a single ''asynchronous'' `ConsoleAppender` which prints all the logging to `System.out` by. An example output would look like:\r
+\r
+ INFO [2016-09-23 15:56:25,498] org.simantics.workbench.internal.SimanticsWorkbenchAdvisor: startPlatform finished\r
+\r
+It is possible to override this default configuration be giving a VM-argument for the application in format:\r
+\r
+ -Dlogback.configurationFile="C:\logbacs\logback.xml"\r
+\r
+For detailed information see [Logback manual](http://logback.qos.ch/manual/).\r
--- /dev/null
+This page contains a comprehensive list of short descriptions for Simantics technical terms with links to more detailed descriptions.\r
+\r
+## Resource\r
+A node in the semantic graph.\r
+\r
+## Statement\r
+An edge in the semantic graph. A triple of Resources (subject, predicate, object).\r
--- /dev/null
+# Simantics Documentation\r
+\r
+This documentation is divided into two chapters:\r
+1. [Developer documentation](Developer/Introduction.md)\r
+2. [End-user documentation](User/Introduction.md)\r
+\r
+![Simantics Logo](Images/Simantics_logo_pile_01.png)\r
--- /dev/null
+# Summary\r
+\r
+* [Preface](README.md)\r
+\r
+### Developer Documentation\r
+\r
+* [Developer Documentation Introduction](Developer/Introduction.md)\r
+\r
+### Overview\r
+\r
+* [Introduction to Simantics Architecture](Developer/Architecture.md)\r
+* [Roadmap](Developer/Roadmap.md)\r
+* [Data View](Developer/DataView.md)\r
+* [Component View](Developer/ComponentView.md)\r
+* [License Information](http://www.simantics.org/download/master/license.html)\r
+\r
+### Development Environment\r
+\r
+* [Git](Developer/Git.md)\r
+\r
+\r
+### Database Development\r
+\r
+* [Interface summary](Developer/Database/InterfaceSummary.md)\r
+* [Resource Adaptation](Developer/Database/ResourceAdaptation.md)\r
+* [Resource Serialization](Developer/Database/ResourceSerialization.md)\r
+* [Inverse Relations](Developer/Database/InverseRelations.md)\r
+* [Virtual Graphs](Developer/Database/VirtualGraphs.md)\r
+* [Functions](Developer/Database/Functions.md)\r
+* [Procedural Values](Developer/Database/ProceduralValues.md)\r
+* [Variable](Developer/Database/Variable.md)\r
+* [Undo Mechanism](Developer/Database/Undo.md)\r
+* [Subgraph Extents](Developer/Database/SubgraphExtents.md)\r
+* [Database Testing](Developer/Database/DatabaseTesting.md)\r
+\r
+### Ontology Development\r
+\r
+* [Graph Compiler](Developer/Ontology/GraphCompiler.md)\r
+* [Transferable Graph](Developer/Ontology/TransferableGraph.md)\r
+* [Binary Container Format](Developer/Ontology/BinaryContainerFormat.md)\r
+* [Graph File Format](Developer/Ontology/GraphFileFormat.md)\r
+* [Version Migration](Developer/Ontology/VersionMigration.md)\r
+\r
+### Data management & Experiment Control\r
+\r
+### Simantics Constraint Language (SCL)\r
+\r
+### Project Development\r
+\r
+### Model Development\r
+\r
+### Data management & Experiment Control\r
+\r
+### Issue Subsystem\r
+\r
+### UI Development\r
+\r
+### Diagram Development\r
+\r
+### Utilities\r
+\r
+* [Simantics Generic File Import](Developer/Utilities/GenericFileImport.md)\r
+* [Logging in Simantics Platform](Developer/Utilities/Logging.md)\r
+\r
+\r
+### End-user Documentation\r
+\r
+* [User Documentation Introduction](User/Introduction.md)\r
--- /dev/null
+# Simantics End User Documentation\r
+\r
+**Simantics** is a software platform for modelling and simulation. The system has client-server architecture with a semantic ontology-based modelling database and Eclipse framework -based client software with plug-in interface. The Simantics platform and many of its components are open source under [Eclipse Public License (EPL)](http://www.eclipse.org/legal/epl-v10.html).\r
+\r
+Simantics platform is used in open source and commercial modelling and simulation products. Simantics comes with System dynamics modelling and simulation tool, which is an open source tool for modelling business processes. [Apros 6](http://www.apros.fi/) is based on the Simantics platform. For more information on Simantics and related projects, visit [Simantics website](http://www.simantics.org/).\r
+\r
+The philosophy of the Simantics platform is to offer an open, high level application platform on which different computational tools can be easily integrated to form a common environment for modelling and simulation. One of the biggest innovations in the Simantics platform is the semantic modelling approach. The data triple engine on the server side enables high performance data management and arbitrary mapping of data. This enables e.g. efficient mapping of simulation and measurement data to the model configuration and its visualisation.\r
+\r
+This *Simantics End User Documentation* provides information on the open source products that have been developed using Simantics platform. The basic principles of Simantics platform and some components common to all Simantics-based products are also explained. If you wish to dig deeper to the foundations of the Simantics platform or create your own modelling and simulation tool based on Simantics, see [Simantics Developer Documentation](../Developer/Introduction.md) or contact us through the [Simantics website](http://www.simantics.org).\r
--- /dev/null
+{\r
+ "gitbook": "3.2.3",\r
+ "structure": {\r
+ "readme": "README.md",\r
+ "summary": "SUMMARY.md",\r
+ "glossary": "GLOSSARY.md"\r
+ },\r
+ "styles": {\r
+ "website": "styles/website.css"\r
+ },\r
+ "plugins": ["heading-anchors", "back-to-top-button", "katex", "-sharing", "feathers-collapsible-menu"],\r
+ "pluginsConfig": {\r
+ }\r
+}\r
--- /dev/null
+{\r
+ "name": "simantics-platform-docs",\r
+ "version": "1.32.0",\r
+ "description": "Simantics Platform Documentation",\r
+ "dependencies": {\r
+ "gitbook-plugin-feathers-collapsible-menu": "^2.2.0",\r
+ "gitbook-plugin-katex": "^1.1.4",\r
+ "gitbook-plugin-prism": "^2.3.0",\r
+ "gitbook-plugin-styles-sass-fix": "^1.1.2",\r
+ "gitbook-plugin-tbobook": "0.0.6",\r
+ "gitbook-plugin-theme-api": "^1.1.2",\r
+ "gitbook-plugin-theme-appcom": "0.0.16",\r
+ "gitbook-plugin-theme-bandwidth": "^1.7.11",\r
+ "gitbook-plugin-theme-blue": "^1.0.15",\r
+ "gitbook-plugin-theme-brcm": "^1.1.18",\r
+ "gitbook-plugin-theme-clarity": "^1.0.4",\r
+ "gitbook-plugin-theme-eus": "^1.0.19",\r
+ "gitbook-plugin-theme-fs": "^2.0.6",\r
+ "gitbook-plugin-theme-gestalt": "^1.0.2",\r
+ "gitbook-plugin-theme-mobdoc": "^7.2.20",\r
+ "gitbook-plugin-theme-opendocs": "0.0.5",\r
+ "gitbook-plugin-theme-redash": "^1.1.3",\r
+ "gitbook-plugin-theme-rms": "0.0.1"\r
+ },\r
+ "devDependencies": {\r
+ "gitbook-cli": "3.2.3"\r
+ },\r
+ "scripts": {\r
+ "docs:prepare": "gitbook install",\r
+ "docs:watch": "npm run docs:prepare && gitbook serve"\r
+ }\r
+}\r
--- /dev/null
+.gitbook-link {\r
+ display: none !important;\r
+}\r
+\r
+.book .markdown-section code {\r
+ padding: 2px 4px;\r
+ font-size: 90%;\r
+ color: #c0341d;\r
+ background-color: #fcedea;\r
+ border-radius: 3px;\r
+}\r
+\r
+kbd {\r
+ display: inline-block;\r
+ padding: 3px 5px;\r
+ font-size: 85% !important;\r
+ line-height: 10px;\r
+ color: #555;\r
+ vertical-align: middle;\r
+ background-color: #fcfcfc;\r
+ border-width: 1px;\r
+ border-style: solid;\r
+ border-color: #ccc #ccc #bbb;\r
+ border-image: none;\r
+ border-radius: 3px;\r
+ box-shadow: 0 -1px 0 #bbb inset;\r
+}\r
+\r
+.book .markdown-section img + em {\r
+ display: block;\r
+ font-size: 90%;\r
+}
\ No newline at end of file
--- /dev/null
+npm run docs:watch
\ No newline at end of file