org.simantics.layer0;bundle-version="1.0.0",
org.simantics.db.common;bundle-version="1.1.0",
org.simantics.structural.ontology;bundle-version="1.1.0",
- org.slf4j.api
+ org.slf4j.api,
+ org.simantics.db.layer0
Export-Package: org.simantics.objmap.backward,
org.simantics.objmap.bidirectional,
org.simantics.objmap.exceptions,
--- /dev/null
+package org.simantics.objmap.graph.annotations;
+
+/*******************************************************************************
+ * Copyright (c) 2019 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
+ *******************************************************************************/
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.simantics.layer0.Layer0;
+import org.simantics.objmap.graph.annotations.meta.IsFieldRule;
+
+/**
+ * This field is a java.util.List or an array type that represents the contents
+ * of a Layer0.List entity that is the single object of the given relation.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@IsFieldRule
+public @interface LinkedList {
+ /**
+ * URI of a relation that has a Layer0.List as its object.
+ */
+ String value();
+ /**
+ * URI of the type of the list resource to create.
+ */
+ String type() default Layer0.URIs.List;
+ boolean composition() default false;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2019 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.objmap.graph.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * An add method add(int index, T value) for a linked list mapped to the single object
+ * of a given relation.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface LinkedListAdd {
+ String value();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2019 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.objmap.graph.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.simantics.layer0.Layer0;
+import org.simantics.objmap.graph.annotations.meta.IsCollectionRule;
+
+/**
+ * A get method that returns the contents of a linked list mapped to the single object of
+ * a given relation.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+@IsCollectionRule
+@HasCollectionAdder(LinkedListAdd.class)
+@HasCollectionRemover(LinkedListRem.class)
+public @interface LinkedListGet {
+ String value();
+ String type() default Layer0.URIs.List;
+ boolean composition() default false;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2019 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.objmap.graph.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Remove method for a list of objects represented by a Layer0.List as the
+ * single object of a given relation.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface LinkedListRem {
+ String value();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2019 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.objmap.graph.annotations.factories;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.Collection;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.ResourceNotFoundException;
+import org.simantics.db.exception.ServiceException;
+import org.simantics.db.exception.ValidationException;
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;
+import org.simantics.objmap.graph.annotations.LinkedList;
+import org.simantics.objmap.graph.rules.MappedElementsRule;
+import org.simantics.objmap.graph.rules.domain.LinkedListAccessor;
+import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory;
+import org.simantics.objmap.graph.rules.range.FieldAccessor;
+
+public class LinkedListRuleFactory<Range> implements IFieldRuleFactory<Resource, Range> {
+
+ @Override
+ public IBidirectionalMappingRule<Resource, Range> create(ReadGraph g, Annotation _annotation, Field field) throws ResourceNotFoundException, ValidationException, ServiceException {
+ LinkedList annotation = (LinkedList)_annotation;
+ return new MappedElementsRule<Resource,Range>(
+ new LinkedListAccessor(g.getResource(annotation.value()), g.getResource(annotation.type()), annotation.composition()),
+ new FieldAccessor<Range,Collection<Range>>(field)
+ );
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2019 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.objmap.graph.annotations.factories;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;
+import org.simantics.objmap.graph.annotations.LinkedListAdd;
+import org.simantics.objmap.graph.annotations.LinkedListGet;
+import org.simantics.objmap.graph.annotations.LinkedListRem;
+import org.simantics.objmap.graph.rules.MappedElementsRule;
+import org.simantics.objmap.graph.rules.domain.LinkedListAccessor;
+import org.simantics.objmap.graph.rules.factory.ICollectionRuleFactory;
+import org.simantics.objmap.graph.rules.range.CollectionAccessor;
+
+public class LinkedListRuleFactory2<Range> implements ICollectionRuleFactory<Resource,Range> {
+
+ @Override
+ public IBidirectionalMappingRule<Resource, Range> create(ReadGraph g, Annotation annotation,
+ Method getter, Method adder, Method remover)
+ throws DatabaseException {
+ LinkedListGet getterAnn = (LinkedListGet)annotation;
+ return new MappedElementsRule<Resource,Range>(new LinkedListAccessor(g.getResource(getterAnn.value()), g.getResource(getterAnn.type()), getterAnn.composition()),
+ new CollectionAccessor<Range,Range>(getter, adder, remover));
+ }
+
+ @Override
+ public boolean isAdder(Annotation getterAnnotation, Annotation annotation) {
+ LinkedListGet getterAnn = (LinkedListGet)getterAnnotation;
+ LinkedListAdd adderAnn = (LinkedListAdd)annotation;
+ return getterAnn.value().equals(adderAnn.value());
+ }
+
+ @Override
+ public boolean isRemover(Annotation getterAnnotation, Annotation annotation) {
+ LinkedListGet getterAnn = (LinkedListGet)getterAnnotation;
+ LinkedListRem adderAnn = (LinkedListRem)annotation;
+ return getterAnn.value().equals(adderAnn.value());
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2019 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.objmap.graph.rules.domain;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.utils.ListUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.objmap.exceptions.MappingException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Accesses the set of objects attached to the element by the given relation.
+ * @author Hannu Niemistö
+ */
+public class LinkedListAccessor implements IDomainAccessor<Resource,Collection<Resource>> {
+
+ static Logger LOGGER = LoggerFactory.getLogger(LinkedListAccessor.class);
+
+ Resource relation;
+ Resource listType;
+ boolean deleteExtraObjects;
+
+ public LinkedListAccessor(Resource relation, Resource listType, boolean deleteExtraObjects) {
+ super();
+ this.relation = relation;
+ this.listType = listType;
+ this.deleteExtraObjects = deleteExtraObjects;
+ }
+
+ @Override
+ public Collection<Resource> get(ReadGraph g, Resource element) throws MappingException {
+ try {
+ LOGGER.info(" LinkdedListAccessor.get");
+ return ListUtils.toList(g, g.getPossibleObject(element, relation));
+ } catch (DatabaseException e) {
+ throw new MappingException(e);
+ }
+ }
+
+ @Override
+ public boolean set(WriteGraph g, Resource element, Collection<Resource> value)
+ throws MappingException {
+ try {
+ LOGGER.info(" LinkdedListAccessor.set");
+ return MappingUtils.synchronizeList(g, element, relation, listType, new ArrayList<Resource>(value), deleteExtraObjects);
+ } catch (DatabaseException e) {
+ throw new MappingException(e);
+ }
+
+ }
+
+}
/*******************************************************************************
- * Copyright (c) 2007, 2013 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2013, 2019 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
*
* Contributors:
* VTT Technical Research Centre of Finland - initial API and implementation
+ * Semantum oy - linked list utilities
*******************************************************************************/
package org.simantics.objmap.graph.rules.domain;
import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.simantics.db.Resource;
import org.simantics.db.WriteGraph;
+import org.simantics.db.common.utils.ListUtils;
import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
+import org.simantics.db.exception.NoSingleResultException;
+import org.simantics.db.exception.ServiceException;
+import org.simantics.layer0.Layer0;
/**
* Static utility methods for rule implementations.
return modified;
}
+ public static boolean synchronizeList(WriteGraph g, Resource element, Resource relation, Resource listType, List<Resource> value, boolean deleteExtraObjects) throws DatabaseException {
+ final Layer0 L0 = Layer0.getInstance(g);
+
+ // Return value
+ boolean modified = false;
+
+ // Get the list - create a new one, if necessary
+ Resource currentList = g.getPossibleObject(element, relation);
+ if (currentList == null) {
+ currentList = ListUtils.create(g, listType);
+ g.claim(element, relation, currentList);
+ modified = true;
+ }
+
+ // Synchronize elements
+ List<Resource> currentNodes = ListUtils.getListNodes(g, currentList);
+ int i = 0, j = 0;
+ while (i < currentNodes.size()) {
+ Resource node = currentNodes.get(i);
+ Resource v = g.getSingleObject(node, L0.List_Element);
+ if (j < value.size() && v.equals(value.get(j))) {
+ i++;
+ j++;
+ }
+ else if (value.indexOf(v) > j) {
+ // Insert new element in the middle
+ insertElementBefore(g, L0, node, value.get(j));
+ modified = true;
+ j++;
+ }
+ else {
+ // Remove deleted element
+ if (deleteExtraObjects) g.deny(v);
+ removeNode(g, L0, node);
+ modified = true;
+ i++;
+ }
+ }
+
+ // Add new elements at end
+ while (j < value.size()) {
+ // Add tailing elements
+ insertElementBefore(g, L0, currentList, value.get(j));
+ modified = true;
+ j++;
+ }
+
+ return modified;
+ }
+
+ private static Resource insertElementBefore(WriteGraph g, final Layer0 L0, Resource node, final Resource val)
+ throws NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException {
+ Resource prev = g.getSingleObject(node, L0.List_Previous);
+ g.deny(prev, L0.List_Next, L0.List_Previous, node);
+
+ Resource newNode = g.newResource();
+ g.claim(newNode, L0.InstanceOf, L0.List_Entry);
+ g.claim(prev, L0.List_Next, L0.List_Previous, newNode);
+ g.claim(newNode, L0.List_Next, L0.List_Previous, node);
+ g.claim(newNode, L0.List_Element, val);
+ return newNode;
+ }
+
+ private static void removeNode(WriteGraph g, final Layer0 L0, Resource node)
+ throws NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException {
+ Resource prev = g.getSingleObject(node, L0.List_Previous);
+ Resource next = g.getSingleObject(node, L0.List_Next);
+ g.claim(prev, L0.List_Next, L0.List_Previous, next);
+ g.deny(node);
+ }
+
}
/*******************************************************************************
- * Copyright (c) 2012, 2013 Association for Decentralized Information Management in
+ * Copyright (c) 2012, 2013, 2019 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
*
* Contributors:
* VTT Technical Research Centre of Finland - initial API and implementation
+ * Semantum oy - linked list mapping API and implementation
*******************************************************************************/
package org.simantics.objmap.graph.schema;
import org.simantics.objmap.graph.annotations.HasCollectionAdder;
import org.simantics.objmap.graph.annotations.HasCollectionRemover;
import org.simantics.objmap.graph.annotations.HasSetter;
+import org.simantics.objmap.graph.annotations.LinkedListGet;
+import org.simantics.objmap.graph.annotations.LinkedList;
import org.simantics.objmap.graph.annotations.OptionalRelatedElements;
import org.simantics.objmap.graph.annotations.OrderedElementsGet;
import org.simantics.objmap.graph.annotations.OrderedSetType;
import org.simantics.objmap.graph.annotations.RelatedValue;
import org.simantics.objmap.graph.annotations.UpdateMethod;
import org.simantics.objmap.graph.annotations.factories.CompoundRelatedGetSetValueRuleFactory;
+import org.simantics.objmap.graph.annotations.factories.LinkedListRuleFactory;
+import org.simantics.objmap.graph.annotations.factories.LinkedListRuleFactory2;
import org.simantics.objmap.graph.annotations.factories.OptionalRelatedElementsRuleFactory;
import org.simantics.objmap.graph.annotations.factories.OrderedElementsRuleFactory;
import org.simantics.objmap.graph.annotations.factories.RelatedElementRuleFactory;
return new OptionalRelatedElementsRuleFactory<Object>();
if (annotation.annotationType().equals(RelatedOrderedSetElements.class))
return new RelatedOrderedSetElementsRuleFactory<Object>();
+ if (annotation.annotationType().equals(LinkedList.class))
+ return new LinkedListRuleFactory<Object>();
return null;
}
return new RelatedElementsRuleFactory2<Object>();
if (annotation.annotationType().equals(OrderedElementsGet.class))
return new OrderedElementsRuleFactory<Object>();
+ if (annotation.annotationType().equals(LinkedListGet.class))
+ return new LinkedListRuleFactory2<>();
return null;
}