Merge branch 'dev'
diff --git a/build.gradle b/build.gradle
index 02b25b0..39aafe9 100644
--- a/build.gradle
+++ b/build.gradle
@@ -22,6 +22,6 @@
dependencies {
// testing
testCompile 'junit:junit:4.12'
- testCompile 'org.mockito:mockito-core:2.+'
+ testCompile 'org.mockito:mockito-core:2.10.0'
testCompile 'org.assertj:assertj-core:3.6.2'
}
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/mdm/api/base/BaseApplicationContext.java b/src/main/java/org/eclipse/mdm/api/base/BaseApplicationContext.java
new file mode 100644
index 0000000..99fda43
--- /dev/null
+++ b/src/main/java/org/eclipse/mdm/api/base/BaseApplicationContext.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2017 Peak Solution GmbH
+ * 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
+ */
+package org.eclipse.mdm.api.base;
+
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.mdm.api.base.adapter.ModelManager;
+import org.eclipse.mdm.api.base.file.FileService;
+import org.eclipse.mdm.api.base.model.BaseEntityFactory;
+import org.eclipse.mdm.api.base.notification.NotificationService;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.search.SearchService;
+
+/**
+ * Base application context represents a connection/session to the underlying data store.
+ * It provides access to managers and services.
+ *
+ * @param <S>
+ * Type of the connected entity factory.
+ * @param <T>
+ * Type of the connected entity manager.
+ * @since 1.0.0
+ */
+public interface BaseApplicationContext<S extends BaseEntityFactory, T extends BaseEntityManager> extends AutoCloseable {
+ /**
+ * The returned service loads entities from the underlying data source.
+ *
+ * @return {@code Optional} is empty if no such service is available.
+ */
+ default Optional<T> getEntityManager() {
+ return Optional.empty();
+ }
+
+ /**
+ * The returned service creates new entities.
+ *
+ * @return {@code Optional} is empty if no such service is available.
+ */
+ default Optional<S> getEntityFactory() {
+ return Optional.empty();
+ }
+
+ /**
+ * The returned service provides access to the application model's meta data.
+ *
+ * @return {@code Optional} is empty if no such service is available.
+ * @see ModelManager
+ */
+ default Optional<ModelManager> getModelManager() {
+ return Optional.empty();
+ }
+
+ /**
+ * The returned service provides advanced search capabilities for supported
+ * entity types.
+ *
+ * @return {@code Optional} is empty if no such service is available.
+ * @see SearchService
+ */
+ default Optional<SearchService> getSearchService() {
+ return Optional.empty();
+ }
+
+ /**
+ * The returned service provides access to the low level query API.
+ *
+ * @return {@code Optional} is empty if no such service is available.
+ * @see QueryService
+ */
+ default Optional<QueryService> getQueryService() {
+ return Optional.empty();
+ }
+
+ /**
+ * The returned service allows to download linked files from the file
+ * storage.
+ *
+ * @return {@code Optional} is empty if no such service is available.
+ * @see FileService
+ */
+ default Optional<FileService> getFileService() {
+ return Optional.empty();
+ }
+
+ /**
+ * The returned service allows to register/unregister for events at a registration service.
+ *
+ * @return {@code Optional} is empty if no such service is available.
+ * @see NotificationService
+ */
+ default Optional<NotificationService> getNotificationService() {
+ return Optional.empty();
+ }
+
+ /**
+ * Returns a map with all configuration parameters, which where given to initialize this context.
+ *
+ * @return map with configuration parameters
+ */
+ Map<String, String> getParameters();
+
+ /**
+ * Closes the BaseContext.
+ *
+ * This closes all underlying managers and services.
+ */
+ void close() throws ConnectionException;
+}
diff --git a/src/main/java/org/eclipse/mdm/api/base/BaseApplicationContextFactory.java b/src/main/java/org/eclipse/mdm/api/base/BaseApplicationContextFactory.java
new file mode 100644
index 0000000..2f0ac30
--- /dev/null
+++ b/src/main/java/org/eclipse/mdm/api/base/BaseApplicationContextFactory.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017 Peak Solution GmbH
+ * 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
+ */
+package org.eclipse.mdm.api.base;
+
+import java.util.Map;
+
+import org.eclipse.mdm.api.base.model.BaseEntityFactory;
+
+/**
+ * Takes connection parameters and produces a corresponding base application context.
+ *
+ * @param <T>
+ * Type of the connected entity manager.
+ * @since 1.0.0
+ */
+public interface BaseApplicationContextFactory<T extends BaseApplicationContext<? extends BaseEntityFactory, ? extends BaseEntityManager>> {
+
+ /**
+ * Takes given connection parameters and creates a new context, which
+ * is permanently connected with configured data source.
+ *
+ * @param connectionParameters
+ * The connection parameters.
+ * @return The connected context is returned.
+ * @throws ConnectionException
+ * Thrown if unable to connect to a data source.
+ */
+ T connect(Map<String, String> connectionParameters) throws ConnectionException;
+}
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/mdm/api/base/BaseEntityManager.java b/src/main/java/org/eclipse/mdm/api/base/BaseEntityManager.java
index b7d8c7b..5a8c399 100644
--- a/src/main/java/org/eclipse/mdm/api/base/BaseEntityManager.java
+++ b/src/main/java/org/eclipse/mdm/api/base/BaseEntityManager.java
@@ -15,7 +15,6 @@
import java.util.Optional;
import org.eclipse.mdm.api.base.massdata.ReadRequest;
-import org.eclipse.mdm.api.base.model.BaseEntityFactory;
import org.eclipse.mdm.api.base.model.ContextDescribable;
import org.eclipse.mdm.api.base.model.ContextRoot;
import org.eclipse.mdm.api.base.model.ContextType;
@@ -26,8 +25,6 @@
import org.eclipse.mdm.api.base.model.TestStep;
import org.eclipse.mdm.api.base.model.User;
import org.eclipse.mdm.api.base.query.DataAccessException;
-import org.eclipse.mdm.api.base.query.ModelManager;
-import org.eclipse.mdm.api.base.query.SearchService;
/**
* Provides business layer CRUD operations and services (CREATE, READ, UPDATE,
@@ -39,53 +36,7 @@
* @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
* @author Sebastian Dirsch, Gigatronik Ingolstadt GmbH
*/
-public interface BaseEntityManager<S extends BaseEntityFactory> {
-
- // ======================================================================
- // Public methods
- // ======================================================================
-
- /**
- * The returned service creates new entities.
- *
- * @return {@code Optional} is empty if no such service is available.
- */
- default Optional<S> getEntityFactory() {
- return Optional.empty();
- }
-
- /**
- * The returned service provides advanced search capabilities for supported
- * entity types.
- *
- * @return {@code Optional} is empty if no such service is available.
- * @see SearchService
- */
- default Optional<SearchService> getSearchService() {
- return Optional.empty();
- }
-
- /**
- * The returned service provides access to the low level query API and the
- * application model's meta data.
- *
- * @return {@code Optional} is empty if no such service is available.
- * @see ModelManager
- */
- default Optional<ModelManager> getModelManager() {
- return Optional.empty();
- }
-
- /**
- * The returned service allows to download linked files from the file
- * storage.
- *
- * @return {@code Optional} is empty if no such service is available.
- * @see FileService
- */
- default Optional<FileService> getFileService() {
- return Optional.empty();
- }
+public interface BaseEntityManager {
/**
* Returns the {@link Environment} this entity manager is connected to.
@@ -337,12 +288,4 @@
*/
Transaction startTransaction() throws DataAccessException;
- /**
- * Closes the connection to the underlying data source.
- *
- * @throws ConnectionException
- * Thrown in case of errors while closing the connection.
- */
- void close() throws ConnectionException;
-
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/EntityManagerFactory.java b/src/main/java/org/eclipse/mdm/api/base/EntityManagerFactory.java
deleted file mode 100644
index e153d44..0000000
--- a/src/main/java/org/eclipse/mdm/api/base/EntityManagerFactory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2016 Gigatronik Ingolstadt GmbH
- * 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
- */
-
-package org.eclipse.mdm.api.base;
-
-import java.util.Map;
-
-import org.eclipse.mdm.api.base.model.BaseEntityFactory;
-
-/**
- * Takes connection parameters and produces a corresponding entity manager.
- *
- * @param <T>
- * Type of the connected entity manager.
- * @since 1.0.0
- * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
- */
-public interface EntityManagerFactory<T extends BaseEntityManager<? extends BaseEntityFactory>> {
-
- // ======================================================================
- // Public methods
- // ======================================================================
-
- /**
- * Takes given connection parameters and creates a new entity manager, which
- * is permanently connected with configured data source.
- *
- * @param connectionParameters
- * The connection parameters.
- * @return The connected entity manager is returned.
- * @throws ConnectionException
- * Thrown if unable to connect to a data source.
- */
- T connect(Map<String, String> connectionParameters) throws ConnectionException;
-
-}
diff --git a/src/main/java/org/eclipse/mdm/api/base/NotificationManagerFactory.java b/src/main/java/org/eclipse/mdm/api/base/NotificationManagerFactory.java
deleted file mode 100644
index 5d51cbb..0000000
--- a/src/main/java/org/eclipse/mdm/api/base/NotificationManagerFactory.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.eclipse.mdm.api.base;
-
-import java.util.Map;
-
-import org.eclipse.mdm.api.base.model.BaseEntityFactory;
-import org.eclipse.mdm.api.base.notification.NotificationManager;
-
-/**
- * Takes a base entity manager and connection parameters and produces a
- * corresponding notification manager.
- *
- * @since 1.0.0
- * @author Matthias Koller, Peak Solution GmbH
- */
-public interface NotificationManagerFactory {
-
- /**
- * Creates a notification manager based on the given entity manager and
- * parameters
- *
- * @param entityManager
- * The entityManager.
- * @param connectionParameters
- * The connection parameters.
- * @return The configured NotificationManager is returned.
- * @throws ConnectionException
- * Thrown if unable to connect to a data source.
- */
- NotificationManager create(BaseEntityManager<? extends BaseEntityFactory> baseEntityManager,
- Map<String, String> parameters) throws ConnectionException;
-}
diff --git a/src/main/java/org/eclipse/mdm/api/base/ServiceNotProvidedException.java b/src/main/java/org/eclipse/mdm/api/base/ServiceNotProvidedException.java
new file mode 100644
index 0000000..f351058
--- /dev/null
+++ b/src/main/java/org/eclipse/mdm/api/base/ServiceNotProvidedException.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017 Peak Solution GmbH and others
+ * 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
+ */
+package org.eclipse.mdm.api.base;
+
+/**
+ * This exception indicates that a service is not provided by an adapter.
+ */
+public class ServiceNotProvidedException extends RuntimeException {
+
+ private static final long serialVersionUID = -4829618036958929415L;
+
+ /**
+ * Constructor.
+ *
+ * @param clazz the service that is not provided
+ */
+ public ServiceNotProvidedException(Class<?> clazz) {
+ super("The service '" + clazz + "' is not implemented!");
+ }
+}
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/Attribute.java b/src/main/java/org/eclipse/mdm/api/base/adapter/Attribute.java
similarity index 98%
rename from src/main/java/org/eclipse/mdm/api/base/query/Attribute.java
rename to src/main/java/org/eclipse/mdm/api/base/adapter/Attribute.java
index 0ef918b..a9539b9 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/Attribute.java
+++ b/src/main/java/org/eclipse/mdm/api/base/adapter/Attribute.java
@@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*/
-package org.eclipse.mdm.api.base.query;
+package org.eclipse.mdm.api.base.adapter;
import org.eclipse.mdm.api.base.model.Enumeration;
import org.eclipse.mdm.api.base.model.Value;
diff --git a/src/main/java/org/eclipse/mdm/api/base/adapter/ChildrenStore.java b/src/main/java/org/eclipse/mdm/api/base/adapter/ChildrenStore.java
new file mode 100644
index 0000000..0eec759
--- /dev/null
+++ b/src/main/java/org/eclipse/mdm/api/base/adapter/ChildrenStore.java
@@ -0,0 +1,103 @@
+package org.eclipse.mdm.api.base.adapter;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.mdm.api.base.model.Deletable;
+
+/**
+ * Holds related entities of any kind and keeps track of modifications.
+ */
+public final class ChildrenStore {
+
+ private final Map<Class<? extends Deletable>, List<? extends Deletable>> current = new HashMap<>(0);
+ private final Map<Class<? extends Deletable>, List<? extends Deletable>> removed = new HashMap<>(0);
+
+ /**
+ * Returns current set of related children mapped by their type.
+ *
+ * @return Returned {@code Map} is unmodifiable.
+ */
+ public Map<Class<? extends Deletable>, List<? extends Deletable>> getCurrent() {
+ return Collections.unmodifiableMap(current);
+ }
+
+ /**
+ * Returns current set of removed related children mapped by their type.
+ *
+ * @return Returned {@code Map} is unmodifiable.
+ */
+ public Map<Class<? extends Deletable>, List<? extends Deletable>> getRemoved() {
+ return Collections.unmodifiableMap(removed);
+ }
+
+ /**
+ * Returns related child entities of given type.
+ *
+ * @param <T>
+ * Desired entity type.
+ * @param entityClass
+ * Used as identifier.
+ * @return Returned {@code List} is unmodifiable.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Deletable> List<T> get(Class<T> entityClass) {
+ return Collections.unmodifiableList((List<T>) current.computeIfAbsent(entityClass, k -> new ArrayList<>()));
+ }
+
+ /**
+ * Sorts the child entities with given {@code Comparator}.
+ *
+ * @param <T>
+ * Desired entity type.
+ * @param entityClass
+ * Used as identifier.
+ * @param comparator
+ * Used for sorting.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Deletable> void sort(Class<T> entityClass, Comparator<? super T> comparator) {
+ List<T> children = (List<T>) current.get(entityClass);
+ if (children != null) {
+ children.sort(comparator);
+ }
+ }
+
+ /**
+ * Adds given child entity.
+ *
+ * @param child
+ * The new child.
+ */
+ @SuppressWarnings("unchecked")
+ public void add(Deletable child) {
+ removed.getOrDefault(child.getClass(), new ArrayList<>()).remove(child);
+ ((List<Deletable>) current.computeIfAbsent(child.getClass(), k -> new ArrayList<>())).add(child);
+ }
+
+ /**
+ * Removes given child entity.
+ *
+ * @param child
+ * The child which will be removed.
+ */
+ @SuppressWarnings("unchecked")
+ public void remove(Deletable child) {
+ List<Deletable> children = (List<Deletable>) current.getOrDefault(child.getClass(), new ArrayList<>());
+ if (children.remove(child) && child.getID() != null && child.getID().length() > 0) {
+ ((List<Deletable>) removed.computeIfAbsent(child.getClass(), k -> new ArrayList<>())).add(child);
+ }
+ }
+
+ /**
+ * Clean up list of removed entities.
+ */
+ void apply() {
+ removed.clear();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/mdm/api/base/adapter/Core.java b/src/main/java/org/eclipse/mdm/api/base/adapter/Core.java
new file mode 100644
index 0000000..cf1fc91
--- /dev/null
+++ b/src/main/java/org/eclipse/mdm/api/base/adapter/Core.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2016 Gigatronik Ingolstadt GmbH
+ * 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
+ */
+
+package org.eclipse.mdm.api.base.adapter;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import org.eclipse.mdm.api.base.model.FileLink;
+import org.eclipse.mdm.api.base.model.Value;
+
+/**
+ * Provides access to the internals of any entity:
+ *
+ * <ul>
+ * <li>name of the data source</li>
+ * <li>name of the type</li>
+ * <li>instance ID</li>
+ * <li>values</li>
+ * <li>added/removed file links</li>
+ * <li>related entities</li>
+ * <li>parent/child entities</li>
+ * </ul>
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public interface Core {
+
+ // ======================================================================
+ // Public methods
+ // ======================================================================
+
+ /**
+ * Returns the name of the data source this entity was retrieved from.
+ *
+ * @return Name of the data source.
+ */
+ String getSourceName();
+
+ /**
+ * Returns the name of the entity type.
+ *
+ * @return Name of the entity type is returned.
+ */
+ String getTypeName();
+
+ /**
+ * Returns the instance ID or {@code 0} if this instance is not yet
+ * persisted.
+ *
+ * @return The instance ID is returned.
+ */
+ String getID();
+
+ /**
+ * Sets an instance ID.
+ *
+ * @param instanceID
+ * The new instance ID.
+ */
+ void setID(String instanceID);
+
+ /**
+ * Returns <i>all</i> {@link Value} containers of this entity.
+ *
+ * @return Values mapped by their name are returned.
+ */
+ Map<String, Value> getValues();
+
+ /**
+ * Hides {@link Value} containers whose name is contained in the given names
+ * {@code Collection}.
+ * E.g. hide attributes from a CatalogComponent when not used in a TemplateComponent.
+ *
+ * @param names
+ * Names of the {@code Value} which shall be hidden.
+ */
+ void hideValues(Collection<String> names);
+
+ /**
+ * Returns <i>all</i> {@link Value} containers, including the hidden ones.
+ *
+ * @return All {@code Value} containers are returned.
+ */
+ Map<String, Value> getAllValues();
+
+ /**
+ * Returns all newly added {@link FileLink}.
+ *
+ * @return New {@code FileLink}s are returned.
+ */
+ default List<FileLink> getAddedFileLinks() {
+ Predicate<FileLink> isRemote = FileLink::isRemote;
+
+ List<FileLink> fileLinks = getValues().values().stream().filter(v -> v.getValueType().isFileLink())
+ .filter(Value::isValid).map(v -> (FileLink) v.extract()).filter(isRemote.negate())
+ .collect(Collectors.toList());
+
+ List<Value> values = getValues().values().stream().filter(v -> v.getValueType().isFileLinkSequence())
+ .filter(Value::isValid).collect(Collectors.toList());
+
+ for (Value value : values) {
+ Arrays.stream((FileLink[]) value.extract()).filter(isRemote.negate()).forEach(fileLinks::add);
+ }
+
+ return fileLinks;
+ }
+
+ /**
+ * Returns all removed {@link FileLink}s.
+ *
+ * @return Removed {@code FileLink}s are returned.
+ */
+ default List<FileLink> getRemovedFileLinks() {
+ Predicate<FileLink> isRemote = FileLink::isRemote;
+
+ List<FileLink> fileLinks = getValues().values().stream().filter(v -> v.getValueType().isFileLink())
+ .filter(Value::isModified).map(v -> (FileLink) v.extractInitial()).filter(Objects::nonNull)
+ .filter(isRemote).collect(Collectors.toList());
+
+ List<Value> values = getValues().values().stream().filter(v -> v.getValueType().isFileLinkSequence())
+ .filter(Value::wasValid).filter(Value::isModified).collect(Collectors.toList());
+
+ for (Value value : values) {
+ List<FileLink> current = Arrays.asList((FileLink[]) value.extract());
+ Arrays.stream((FileLink[]) value.extractInitial()).filter(fl -> !current.contains(fl))
+ .forEach(fileLinks::add);
+ }
+
+ return fileLinks;
+ }
+
+ /**
+ * Applies modifications made to the entity stores and {@link Value}
+ * containers. This method is called when a transaction is finalized
+ * (all operations completed successfully) to reflect the new state in
+ * the core.
+ */
+ default void apply() {
+ // apply the removed state to mutable entities
+ getMutableStore().apply();
+
+ // apply the removed state to children
+ getChildrenStore().apply();
+
+ // apply modified values
+ getValues().values().stream().filter(Value::isModified).forEach(Value::apply);
+ }
+
+ /**
+ * Returns the mutable {@link EntityStore}.
+ * Holds entities with mutable (editable) relations to the entity
+ * bound to this core instance.
+ * This store only contains always only one relation for one entity.
+ * For child relations use {@link ChildrenStore}.
+ *
+ * @return The mutable {@code EntityStore} is returned.
+ */
+ EntityStore getMutableStore();
+
+ /**
+ * Returns the permanent {@link EntityStore}.
+ * Holds entities with immutable (non-editable) relations to the entity
+ * bound to this core instance.
+ * E.g. relations to the parent entity.
+ *
+ * @return The permanent {@code EntityStore} is returned.
+ */
+ EntityStore getPermanentStore();
+
+ /**
+ * Returns the {@link ChildrenStore}. This store holds child
+ * entities with relations to the entity bound to this core instance.
+ *
+ * @return The {@code ChildrenStore} is returned.
+ */
+ // TODO (8.11.2017; Florian Schmitt, Angelika Wittek)
+ // Entities with more than one related entity that do not refer to children, have also to go here,
+ // as it is not permitted to go to the other stores. Does this work at all?
+ ChildrenStore getChildrenStore();
+
+}
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/DefaultCore.java b/src/main/java/org/eclipse/mdm/api/base/adapter/DefaultCore.java
similarity index 97%
rename from src/main/java/org/eclipse/mdm/api/base/query/DefaultCore.java
rename to src/main/java/org/eclipse/mdm/api/base/adapter/DefaultCore.java
index 7b8521c..90e27fa 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/DefaultCore.java
+++ b/src/main/java/org/eclipse/mdm/api/base/adapter/DefaultCore.java
@@ -6,15 +6,15 @@
* http://www.eclipse.org/legal/epl-v10.html
*/
-package org.eclipse.mdm.api.base.query;
+package org.eclipse.mdm.api.base.adapter;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
-import org.eclipse.mdm.api.base.model.Core;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.query.Record;
/**
* Provides access to the internals of any entity:
diff --git a/src/main/java/org/eclipse/mdm/api/base/adapter/EntityStore.java b/src/main/java/org/eclipse/mdm/api/base/adapter/EntityStore.java
new file mode 100644
index 0000000..a66c69d
--- /dev/null
+++ b/src/main/java/org/eclipse/mdm/api/base/adapter/EntityStore.java
@@ -0,0 +1,185 @@
+package org.eclipse.mdm.api.base.adapter;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.mdm.api.base.model.ContextType;
+import org.eclipse.mdm.api.base.model.Entity;
+
+/**
+ * Holds related entities of any kind and keeps track of modifications.
+ */
+public final class EntityStore {
+
+ private final Map<String, Entity> current = new HashMap<>(0);
+ private final Map<String, Entity> removed = new HashMap<>(0);
+
+ /**
+ * Returns current set of related entities.
+ *
+ * @return Returned {@code Collection} is unmodifiable.
+ */
+ public Collection<Entity> getCurrent() {
+ return Collections.unmodifiableCollection(current.values());
+ }
+
+ /**
+ * Returns current set of removed related entities.
+ *
+ * @return Returned {@code Collection} is unmodifiable.
+ */
+ public Collection<Entity> getRemoved() {
+ return Collections.unmodifiableCollection(removed.values());
+ }
+
+ /**
+ * Returns related entity identified by given entity class.
+ *
+ * @param <T>
+ * The desired entity type.
+ * @param entityClass
+ * Used as identifier.
+ * @return The related entity is returned or null of not defined.
+ */
+ public <T extends Entity> T get(Class<T> entityClass) {
+ return get(entityClass.getSimpleName(), entityClass);
+ }
+
+ /**
+ * Returns related entity identified by given entity class.
+ *
+ * @param <T>
+ * The desired entity type.
+ * @param relationName
+ * The relation name the entity is referenced by.
+ * @param entityClass
+ * Used as identifier.
+ * @return The related entity is returned or null of not defined.
+ */
+ public <T extends Entity> T get(String relationName, Class<T> entityClass) {
+ return entityClass.cast(current.get(relationName));
+ }
+
+ /**
+ * Replaces a related entity with the given one.
+ *
+ * @param entity
+ * The new related entity.
+ */
+ public void set(Entity entity) {
+ set(entity.getClass().getSimpleName(), entity);
+ }
+
+ /**
+ * Replaces a related entity with the given one.
+ *
+ * @param name
+ * The name of the relation the entity is referenced by.
+ * @param entity
+ * The new related entity.
+ */
+ public void set(String name, Entity entity) {
+ Entity old = current.put(name, entity);
+ if (old != null) {
+ removed.put(name, old);
+ }
+ }
+
+ /**
+ * Removes a related entity for given entity class.
+ *
+ * @param entityClass
+ * Used as identifier.
+ */
+ public void remove(Class<? extends Entity> entityClass) {
+ String key = entityClass.getSimpleName();
+ remove(key, entityClass);
+ }
+
+ /**
+ * Removes a related entity for given relation name and entity class.
+ *
+ * @param name
+ * The name of the relation the entity is referenced by.
+ * @param entityClass
+ * Used as identifier.
+ */
+ public void remove(String name, Class<? extends Entity> entityClass) {
+ Entity old = current.remove(name);
+ if (old != null) {
+ removed.put(name, old);
+ }
+ }
+
+ /**
+ * Returns related entity identified by given entity class and
+ * {@link ContextType}.
+ *
+ * @param <T>
+ * The desired entity type.
+ * @param entityClass
+ * Used as identifier.
+ * @param contextType
+ * Used as identifier.
+ * @return The related entity is returned or null of not defined.
+ */
+ public <T extends Entity> T get(Class<T> entityClass, ContextType contextType) {
+ return entityClass.cast(current.get(createContextTypeKey(entityClass, contextType)));
+ }
+
+ /**
+ * Replaces a related entity with the given one.
+ *
+ * @param entity
+ * The new related entity.
+ * @param contextType
+ * Used as identifier.
+ */
+ public void set(Entity entity, ContextType contextType) {
+ String key = createContextTypeKey(entity.getClass(), contextType);
+ Entity old = current.put(key, entity);
+ if (old != null) {
+ removed.put(key, old);
+ }
+ }
+
+ /**
+ * Removes a related entity for given entity class and
+ * {@link ContextType}.
+ *
+ * @param entityClass
+ * Used as identifier.
+ * @param contextType
+ * Used as identifier.
+ */
+ public void remove(Class<? extends Entity> entityClass, ContextType contextType) {
+ String key = createContextTypeKey(entityClass, contextType);
+ Entity old = current.remove(key);
+ if (old != null) {
+ removed.put(key, old);
+ }
+ }
+
+ /**
+ * Clean up list of removed entities.
+ */
+ void apply() {
+ removed.clear();
+ }
+
+ /**
+ * Generates a key from given entity class and {@link ContextType}.
+ *
+ * @param entityClass
+ * Identifier part 1.
+ * @param contextType
+ * Identifier part 2.
+ * @return A context type dependent key is returned.
+ */
+ private static String createContextTypeKey(Class<? extends Entity> entityClass, ContextType contextType) {
+ return entityClass.getSimpleName() + '_' + contextType;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/EntityType.java b/src/main/java/org/eclipse/mdm/api/base/adapter/EntityType.java
similarity index 98%
rename from src/main/java/org/eclipse/mdm/api/base/query/EntityType.java
rename to src/main/java/org/eclipse/mdm/api/base/adapter/EntityType.java
index 3540e33..31a6a1d 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/EntityType.java
+++ b/src/main/java/org/eclipse/mdm/api/base/adapter/EntityType.java
@@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*/
-package org.eclipse.mdm.api.base.query;
+package org.eclipse.mdm.api.base.adapter;
import java.util.List;
import java.util.Map;
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/ModelManager.java b/src/main/java/org/eclipse/mdm/api/base/adapter/ModelManager.java
similarity index 94%
rename from src/main/java/org/eclipse/mdm/api/base/query/ModelManager.java
rename to src/main/java/org/eclipse/mdm/api/base/adapter/ModelManager.java
index 7c831fb..03d0e82 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/ModelManager.java
+++ b/src/main/java/org/eclipse/mdm/api/base/adapter/ModelManager.java
@@ -6,12 +6,13 @@
* http://www.eclipse.org/legal/epl-v10.html
*/
-package org.eclipse.mdm.api.base.query;
+package org.eclipse.mdm.api.base.adapter;
import java.util.List;
import org.eclipse.mdm.api.base.model.ContextType;
import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.query.Query;
/**
* Provides access to any modeled {@link EntityType} within an underlying
@@ -29,13 +30,6 @@
// ======================================================================
/**
- * Creates a new and empty {@link Query}.
- *
- * @return Created {@code Query} is returned.
- */
- Query createQuery();
-
- /**
* Returns all available {@link EntityType}s.
*
* @return The returned {@code List} is unmodifiable.
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/Relation.java b/src/main/java/org/eclipse/mdm/api/base/adapter/Relation.java
similarity index 98%
rename from src/main/java/org/eclipse/mdm/api/base/query/Relation.java
rename to src/main/java/org/eclipse/mdm/api/base/adapter/Relation.java
index 4b76edd..bc667ba 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/Relation.java
+++ b/src/main/java/org/eclipse/mdm/api/base/adapter/Relation.java
@@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*/
-package org.eclipse.mdm.api.base.query;
+package org.eclipse.mdm.api.base.adapter;
import org.eclipse.mdm.api.base.model.Value;
import org.eclipse.mdm.api.base.model.ValueType;
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/RelationType.java b/src/main/java/org/eclipse/mdm/api/base/adapter/RelationType.java
similarity index 96%
rename from src/main/java/org/eclipse/mdm/api/base/query/RelationType.java
rename to src/main/java/org/eclipse/mdm/api/base/adapter/RelationType.java
index 85de713..02b09aa 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/RelationType.java
+++ b/src/main/java/org/eclipse/mdm/api/base/adapter/RelationType.java
@@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*/
-package org.eclipse.mdm.api.base.query;
+package org.eclipse.mdm.api.base.adapter;
/**
* RelationType enumeration.
diff --git a/src/main/java/org/eclipse/mdm/api/base/FileService.java b/src/main/java/org/eclipse/mdm/api/base/file/FileService.java
similarity index 99%
rename from src/main/java/org/eclipse/mdm/api/base/FileService.java
rename to src/main/java/org/eclipse/mdm/api/base/file/FileService.java
index 34e64f1..8ceb888 100644
--- a/src/main/java/org/eclipse/mdm/api/base/FileService.java
+++ b/src/main/java/org/eclipse/mdm/api/base/file/FileService.java
@@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*/
-package org.eclipse.mdm.api.base;
+package org.eclipse.mdm.api.base.file;
import java.io.IOException;
import java.io.InputStream;
diff --git a/src/main/java/org/eclipse/mdm/api/base/massdata/ExternalComponent.java b/src/main/java/org/eclipse/mdm/api/base/massdata/ExternalComponent.java
index 14b2ce7..e65db3f 100644
--- a/src/main/java/org/eclipse/mdm/api/base/massdata/ExternalComponent.java
+++ b/src/main/java/org/eclipse/mdm/api/base/massdata/ExternalComponent.java
@@ -11,35 +11,4 @@
public final class ExternalComponent {
// TODO
-
- // public vwg.audi.mdm.api.TypeSpec aTypeSpec;
- // public int length;
- // public int startOffset;
- // public int blocksize;
- // public int valuesPerBlock;
- // public int valueOffset;
- // public java.lang.String filenameURL;
- // public java.lang.String flagsFileNameURL;
- // public int flagsStartOffset;
- // public short bitCount;
- // public short bitOffset;
- // public ExternalComponentStruct(vwg.audi.mdm.api.TypeSpec aTypeSpec, int
- // length, int startOffset, int blocksize,
- // int valuesPerBlock, int valueOffset, java.lang.String filenameURL,
- // java.lang.String flagsFileNameURL,
- // int flagsStartOffset, short bitCount, short bitOffset)
- // {
- // this.aTypeSpec = aTypeSpec;
- // this.length = length;
- // this.startOffset = startOffset;
- // this.blocksize = blocksize;
- // this.valuesPerBlock = valuesPerBlock;
- // this.valueOffset = valueOffset;
- // this.filenameURL = filenameURL;
- // this.flagsFileNameURL = flagsFileNameURL;
- // this.flagsStartOffset = flagsStartOffset;
- // this.bitCount = bitCount;
- // this.bitOffset = bitOffset;
- // }
-
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/massdata/WriteRequest.java b/src/main/java/org/eclipse/mdm/api/base/massdata/WriteRequest.java
index 1447c00..a5883cc 100644
--- a/src/main/java/org/eclipse/mdm/api/base/massdata/WriteRequest.java
+++ b/src/main/java/org/eclipse/mdm/api/base/massdata/WriteRequest.java
@@ -303,55 +303,6 @@
* The {@link Unit} of the measured values.
*/
void setSourceUnit(Unit sourceUnit) {
- // Unit targetUnit = getChannel().getUnit();
- //
- // if(!targetUnit.nameMatches(sourceUnit.getName())) {
- // if(!targetUnit.getPhysicalDimension().nameMatches(sourceUnit.getPhysicalDimension().getName()))
- // {
- // // conversion is not possible!
- // //
- // // different physical dimensions -> replace Unit of channel with
- // given sourceUnit!
- // // MeaQuantityImpl.addDataValues()
- // //
- // // or simply throw an exception?!
- // // MeaQuantityImpl.addDataFromExternalComponentInUnit
- // //
- // // what to do?!
- // }
- //
- // // convert from source to target unit!
- // SequenceRepresentation sequenceRepresentation =
- // getSequenceRepresentation();
- // if(sequenceRepresentation.isExplicit()) {
- // if(sequenceRepresentation.isExternal()) {
- // // values stored in file so what to do?!
- // // switch sequenceRepresentation to
- // SequenceRepresentation.RAW_LINEAR?
- // } else {
- // // convert this.values
- // }
- // } else if(sequenceRepresentation.isImplicit()) {
- // // adjust generation parameters
- // // ATTENTION -> generation parameters are stored in this.values! (new
- // ODS standard!)
- // } else {
- // // adjust generation parameters for all other SeqReps....
- // }
- //
- //
- //
- // // Problematik bei Umrechnung impliziter INTEGER Kanäle -> Anpassen
- // des RAW Datentyps?!
- //
- // // Problematik bei Umrechung Einheit in dB zu Einheit in nicht dB
- // // Problematik bei Umrechung Einheit in nicht dB zu Einheit in dB
- //
- // // should we do this implicitly within the WritRequest?!
- // // ==> implementation is central and adapter implementation
- // independent!
- // }
-
throw new UnsupportedOperationException("Conversion between units is not implemented yet.");
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/massdata/WriteRequestBuilder.java b/src/main/java/org/eclipse/mdm/api/base/massdata/WriteRequestBuilder.java
index 43b7832..dea271d 100644
--- a/src/main/java/org/eclipse/mdm/api/base/massdata/WriteRequestBuilder.java
+++ b/src/main/java/org/eclipse/mdm/api/base/massdata/WriteRequestBuilder.java
@@ -279,61 +279,4 @@
getWriteRequest().setGenerationParameters(new double[] { offset, factor, calibration });
return new ComplexNumericalValuesBuilder(getWriteRequest());
}
-
- // public Object explicitExternal() {
- // writeRequest.setSequenceRepresentation(SequenceRepresentation.EXPLICIT_EXTERNAL);
- // // TODO new builder for external component structure for all types
- // // subsequent builder should route to independency builder for sortable
- // types
- // // (byte, short, int, long, float, double, date)
- // // see #explicit()
- // throw new UnsupportedOperationException("Not implemented.");
- // }
- //
- // public Object rawLinearExternal(double offset, double factor) {
- // writeRequest.setSequenceRepresentation(SequenceRepresentation.RAW_LINEAR_EXTERNAL);
- // writeRequest.setGenerationParameters(new double[] { offset, factor });
- //
- // // TODO new builder for external component structure for numerical, non
- // complex, types
- // // subsequent builder should route to independency builder
- // // see #rawLinear(offset, factor)
- // throw new UnsupportedOperationException("Not implemented.");
- // }
- //
- // public Object rawPolynomialExternal(double... coefficients) {
- // if(coefficients == null || coefficients.length < 2) {
- // throw new IllegalArgumentException("Coefficients either missing or their
- // length is "
- // + "inconsitent with given grade");
- // }
- // writeRequest.setSequenceRepresentation(SequenceRepresentation.RAW_POLYNOMIAL_EXTERNAL);
- //
- // double[] generationParameters = new double[coefficients.length + 1];
- // generationParameters[0] = coefficients.length - 1;
- // System.arraycopy(coefficients, 0, generationParameters, 1,
- // coefficients.length);
- // writeRequest.setGenerationParameters(generationParameters);
- //
- // // TODO new builder for external component structure for numerical, non
- // complex, types
- // // subsequent builder should route to independency builder (or should
- // this be preventd!?)
- // // see #rawLinear(offset, factor)
- // throw new UnsupportedOperationException("Not implemented.");
- // }
- //
- // public Object rawLinearCalibratedExternal(double offset, double factor,
- // double calibration) {
- // writeRequest.setSequenceRepresentation(SequenceRepresentation.RAW_LINEAR_CALIBRATED_EXTERNAL);
- // writeRequest.setGenerationParameters(new double[] { offset, factor,
- // calibration });
- //
- // // TODO new builder for external component structure for numerical, non
- // complex, types
- // // subsequent builder should route to independency builder
- // // see #rawLinear(offset, factor)
- // throw new UnsupportedOperationException("Not implemented.");
- // }
-
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/AxisType.java b/src/main/java/org/eclipse/mdm/api/base/model/AxisType.java
index 2576bbb..7df7446 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/AxisType.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/AxisType.java
@@ -16,30 +16,22 @@
* @author Sebastian Dirsch, Gigatronik Ingolstadt GmbH
* @see Channel
*/
-public class AxisType extends EnumerationValue{
-
- // ======================================================================
- // Enumerations
- // ======================================================================
+public class AxisType extends EnumerationValue {
/**
* A {@link Channel} of this type may be displayed as the x-axis.
*/
- public static final AxisType X_AXIS = new AxisType();
+ public static final AxisType X_AXIS = new AxisType(0);
/**
* A {@link Channel} of this type may be displayed as the y-axis.
*/
- public static final AxisType Y_AXIS = new AxisType();
+ public static final AxisType Y_AXIS = new AxisType(1);
/**
* A {@link Channel} of this type may be displayed as the x- or y-axis.
*/
- public static final AxisType XY_AXIS = new AxisType();
-
- // ======================================================================
- // Public methods
- // ======================================================================
+ public static final AxisType XY_AXIS = new AxisType(2);
/**
* Returns true if this axis type is {@link #X_AXIS}.
@@ -71,4 +63,11 @@
return XY_AXIS == this;
}
+ /**
+ * Constructor, makes sure that the order matches the order of the static
+ * fields
+ */
+ AxisType(int ord) {
+ super(ord);
+ }
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/BaseEntity.java b/src/main/java/org/eclipse/mdm/api/base/model/BaseEntity.java
index 869be38..cf548b1 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/BaseEntity.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/BaseEntity.java
@@ -12,6 +12,8 @@
import java.util.Map;
import java.util.stream.Collectors;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* This is a base implementation for modeled entities. API consumers should
* never use this class in any way, instead the most common interface should be
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/BaseEntityFactory.java b/src/main/java/org/eclipse/mdm/api/base/model/BaseEntityFactory.java
index e9362e6..a254dae 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/BaseEntityFactory.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/BaseEntityFactory.java
@@ -8,12 +8,15 @@
package org.eclipse.mdm.api.base.model;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
-import org.eclipse.mdm.api.base.model.Core.ChildrenStore;
-import org.eclipse.mdm.api.base.model.Core.EntityStore;
+import org.eclipse.mdm.api.base.adapter.ChildrenStore;
+import org.eclipse.mdm.api.base.adapter.Core;
+import org.eclipse.mdm.api.base.adapter.EntityStore;
/**
* Implementation of an abstract entity factory which creates new entities.
@@ -57,14 +60,10 @@
Channel channel = new Channel(createCore(Channel.class));
// relations
- getPermanentStore(channel).set(measurement);
- getChildrenStore(measurement).add(channel);
- getMutableStore(channel).set(quantity.getDefaultUnit());
- getMutableStore(channel).set(quantity);
-
- // if(contextSensor != null) {
- // channel.getCore().setInfoRelation(contextSensor);
- // }
+ getCore(channel).getPermanentStore().set(measurement);
+ getCore(measurement).getChildrenStore().add(channel);
+ getCore(channel).getMutableStore().set(quantity.getDefaultUnit());
+ getCore(channel).getMutableStore().set(quantity);
// properties
channel.setName(name);
@@ -98,8 +97,8 @@
ChannelGroup channelGroup = new ChannelGroup(createCore(ChannelGroup.class));
// relations
- getPermanentStore(channelGroup).set(measurement);
- getChildrenStore(measurement).add(channelGroup);
+ getCore(channelGroup).getPermanentStore().set(measurement);
+ getCore(measurement).getChildrenStore().add(channelGroup);
// properties
channelGroup.setName(name);
@@ -123,10 +122,10 @@
Measurement measurement = new Measurement(createCore(Measurement.class));
// relations
- getPermanentStore(measurement).set(testStep);
- getChildrenStore(testStep).add(measurement);
+ getCore(measurement).getPermanentStore().set(testStep);
+ getCore(testStep).getChildrenStore().add(measurement);
for (ContextRoot contextRoot : contextRoots) {
- getMutableStore(measurement).set(contextRoot, contextRoot.getContextType());
+ getCore(measurement).getMutableStore().set(contextRoot, contextRoot.getContextType());
}
// properties
@@ -161,8 +160,8 @@
Parameter parameter = new Parameter(createCore(Parameter.class));
// relations
- getPermanentStore(parameter).set(parameterSet);
- getChildrenStore(parameterSet).add(parameter);
+ getCore(parameter).getPermanentStore().set(parameterSet);
+ getCore(parameterSet).getChildrenStore().add(parameter);
// properties
parameter.setName(name);
@@ -186,8 +185,8 @@
ParameterSet parameterSet = new ParameterSet(createCore(ParameterSet.class));
// relations
- getPermanentStore(parameterSet).set(measurement);
- getChildrenStore(measurement).add(parameterSet);
+ getCore(parameterSet).getPermanentStore().set(measurement);
+ getCore(measurement).getChildrenStore().add(parameterSet);
// properties
parameterSet.setName(name);
@@ -211,8 +210,8 @@
ParameterSet parameterSet = new ParameterSet(createCore(ParameterSet.class));
// relations
- getPermanentStore(parameterSet).set(channel);
- getChildrenStore(channel).add(parameterSet);
+ getCore(parameterSet).getPermanentStore().set(channel);
+ getCore(channel).getChildrenStore().add(parameterSet);
// properties
parameterSet.setName(name);
@@ -258,7 +257,7 @@
Quantity quantity = new Quantity(createCore(Quantity.class));
// relations
- getMutableStore(quantity).set(defaultUnit);
+ getCore(quantity).getMutableStore().set(defaultUnit);
// properties
quantity.setName(name);
@@ -290,7 +289,7 @@
Optional<User> responsiblePerson = getLoggedInUser();
if (responsiblePerson.isPresent()) {
// may be null if user entities are not available
- getMutableStore(test).set(responsiblePerson.get());
+ getCore(test).getMutableStore().set(responsiblePerson.get());
}
// properties
@@ -313,8 +312,8 @@
TestStep testStep = new TestStep(createCore(TestStep.class));
// relations
- getPermanentStore(testStep).set(test);
- getChildrenStore(test).add(testStep);
+ getCore(testStep).getPermanentStore().set(test);
+ getCore(test).getChildrenStore().add(testStep);
// properties
testStep.setName(name);
@@ -325,7 +324,7 @@
// highest sort index in use will be queried before written
testStep.setSortIndex(Integer.valueOf(-1));
} else {
- testStep.setSortIndex(nextIndex(getChildrenStore(test).get(TestStep.class)));
+ testStep.setSortIndex(nextIndex(getCore(test).getChildrenStore().get(TestStep.class)));
}
return testStep;
@@ -344,7 +343,7 @@
Unit unit = new Unit(createCore(Unit.class));
// relations
- getMutableStore(unit).set(physicalDimension);
+ getCore(unit).getMutableStore().set(physicalDimension);
// properties
unit.setName(name);
@@ -412,8 +411,8 @@
ContextComponent contextComponent = new ContextComponent(createCore(name, ContextComponent.class));
// relations
- getPermanentStore(contextComponent).set(contextRoot);
- getChildrenStore(contextRoot).add(contextComponent);
+ getCore(contextComponent).getPermanentStore().set(contextRoot);
+ getCore(contextRoot).getChildrenStore().add(contextComponent);
// properties
contextComponent.setName(name);
@@ -433,8 +432,8 @@
protected ContextSensor createContextSensor(String name, ContextComponent contextComponent) {
ContextSensor contextSensor = new ContextSensor(createCore(name, ContextSensor.class));
// relations
- getPermanentStore(contextSensor).set(contextComponent);
- getChildrenStore(contextComponent).add(contextSensor);
+ getCore(contextSensor).getPermanentStore().set(contextComponent);
+ getCore(contextComponent).getChildrenStore().add(contextSensor);
// properties
contextSensor.setName(name);
@@ -451,59 +450,128 @@
* @return {@code 1} is returned if given {@code List} is empty, otherwise
* the max sort index increased by 1 is returned.
*/
- protected final Integer nextIndex(List<? extends Sortable> sortables) {
+ protected static final Integer nextIndex(List<? extends Sortable> sortables) {
Optional<Integer> maxIndex = sortables.stream().max(Sortable.COMPARATOR).map(Sortable::getSortIndex);
return Integer.valueOf(maxIndex.isPresent() ? maxIndex.get().intValue() + 1 : 1);
}
/**
* Returns the {@link ChildrenStore} for given {@link BaseEntity}.
+ * Please be aware that the contents of this store is subject
+ * to the adapter creating it. It is up to the adapter to decide
+ * which related entities are included.
+ * As there are adapter specific details to the contents of the store it
+ * should be protected from external access.
+ * Therefore by declaring this method protected, the
+ * related functionality is hidden from other classes since the only
+ * classes which can access them (outside this package) are derivatives of
+ * BaseEntityFactory, and it is through such derivatives that BaseEntity's
+ * Stores should be accessed elsewhere if needed.
*
* @param entity
* The {@code BaseEntity} whose {@code ChildrenStore} will be
* returned.
* @return The {@code ChildrenStore} is returned.
*/
- protected final ChildrenStore getChildrenStore(BaseEntity entity) {
+ protected static ChildrenStore getChildrenStore(BaseEntity entity) {
return getCore(entity).getChildrenStore();
}
/**
* Returns the mutable {@link EntityStore} for given {@link BaseEntity}.
+ * Please be aware that the contents of this store is subject
+ * to the adapter creating it. It is up to the adapter to decide
+ * which related entities are included.
+ * As there are adapter specific details to the contents of the store it
+ * should be protected from external access.
+ * Therefore by declaring this method protected, the
+ * related functionality is hidden from other classes since the only
+ * classes which can access them (outside this package) are derivatives of
+ * BaseEntityFactory, and it is through such derivatives that BaseEntity's
+ * Stores should be accessed elsewhere if needed.
+ *
*
* @param entity
* The {@code BaseEntity} whose {@code ChildrenStore} will be
* returned.
* @return The mutable {@code EntityStore} is returned.
*/
- protected final EntityStore getMutableStore(BaseEntity entity) {
+ protected static EntityStore getMutableStore(BaseEntity entity) {
return getCore(entity).getMutableStore();
}
/**
* Returns the permanent {@link EntityStore} for given {@link BaseEntity}.
- *
+ * Please be aware that the contents of this store is subject
+ * to the adapter creating it. It is up to the adapter to decide
+ * which related entities are included.
+ * As there are adapter specific details to the contents of the store it
+ * should be protected from external access.
+ * Therefore by declaring this method protected, the
+ * related functionality is hidden from other classes since the only
+ * classes which can access them (outside this package) are derivatives of
+ * BaseEntityFactory, and it is through such derivatives that BaseEntity's
+ * Stores should be accessed elsewhere if needed.
+ *
* @param entity
* The {@code BaseEntity} whose {@code ChildrenStore} will be
* returned.
* @return The permanent {@code EntityStore} is returned.
*/
- protected final EntityStore getPermanentStore(BaseEntity entity) {
+ protected static EntityStore getPermanentStore(BaseEntity entity) {
return getCore(entity).getPermanentStore();
}
/**
- * Returns {@link Core} of given {@link Entity}.
+ * Returns {@link Core} of given {@link Entity}. Uses protected method from
+ * BaseEntity, which is accessible here as BaseEntity resides in the same
+ * package as BaseEntityFactory. By declaring this method protected, the
+ * Core-related functionality is hidden from other classes since the only
+ * classes which can access them (outside this package) are derivatives of
+ * BaseEntityFactory, and it is through such derivatives that a BaseEntity's
+ * Core should be accessed elsewhere if needed.
*
* @param entity
* The {@code BaseEntity} whose {@code Core} is required.
* @return The {@code Core} is returned.
*/
- protected final Core getCore(BaseEntity entity) {
+ protected static final Core getCore(BaseEntity entity) {
return entity.getCore();
}
/**
+ * Create an instance of {@link BaseEntity} (or derivative) with core as the
+ * instance's {@link Core}. By declaring this method protected, the Core-related
+ * functionality is hidden from other classes since the only classes which can
+ * access them (outside this package) are derivatives of BaseEntityFactory, and
+ * it is through such derivatives that a BaseEntity's Core should be accessed
+ * elsewhere if needed.
+ * <br> <br>
+ * This method accesses the (usually protected) Constructor(Core) of clazz, so
+ * this method should be overridden in a derived class and call
+ * super.createBaseEntity() if that constructor is invisible from the derived
+ * class.
+ *
+ * @param clazz
+ * The class to instantiate, must extend {@link BaseEntity}.
+ * @param core
+ * The {@link Core} to use for the newly created instance.
+ * @return The newly created instance.
+ */
+ protected <T extends BaseEntity> T createBaseEntity(Class<T> clazz, Core core) {
+ try {
+ Constructor<T> constructor = clazz.getDeclaredConstructor(Core.class);
+ try {
+ return constructor.newInstance(core);
+ } catch (IllegalAccessException exc) {
+ throw new IllegalStateException("Cannot access Constructor(Core) of class '" + clazz.getName() + "'!");
+ }
+ } catch (NoSuchMethodException | InvocationTargetException | InstantiationException exc) {
+ throw new IllegalStateException(exc.getMessage(), exc);
+ }
+ }
+
+ /**
* Returns the {@link User} which is bound to the current session.
*
* @return {@code Optional} is empty if {@code User} entities do not exist.
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/BaseParameter.java b/src/main/java/org/eclipse/mdm/api/base/model/BaseParameter.java
index 43b47a7..9594224 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/BaseParameter.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/BaseParameter.java
@@ -9,9 +9,13 @@
package org.eclipse.mdm.api.base.model;
import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of an abstract parameter which holds a value with one of the
* supported {@link ValueType}s listed below. The value is internally stored in
@@ -52,6 +56,7 @@
*/
public abstract class BaseParameter extends BaseEntity implements Deletable {
+ private static final Map<ScalarType, Function<String, Object>> SCALARTYPE_FUNCTION_MAP = new HashMap<>();
// ======================================================================
// Instance variables
// ======================================================================
@@ -59,6 +64,19 @@
private final String attrScalarType;
private final String attrValue;
+ static {
+ SCALARTYPE_FUNCTION_MAP.put(ScalarType.STRING, v -> v);
+ SCALARTYPE_FUNCTION_MAP.put(ScalarType.DATE, v -> LocalDateTime.parse(v, Value.LOCAL_DATE_TIME_FORMATTER));
+ SCALARTYPE_FUNCTION_MAP.put(ScalarType.BOOLEAN, Boolean::valueOf);
+ SCALARTYPE_FUNCTION_MAP.put(ScalarType.BYTE, Byte::valueOf);
+ SCALARTYPE_FUNCTION_MAP.put(ScalarType.SHORT, Short::valueOf);
+ SCALARTYPE_FUNCTION_MAP.put(ScalarType.INTEGER, Integer::valueOf);
+ SCALARTYPE_FUNCTION_MAP.put(ScalarType.LONG, Long::valueOf);
+ SCALARTYPE_FUNCTION_MAP.put(ScalarType.FLOAT, Float::valueOf);
+ SCALARTYPE_FUNCTION_MAP.put(ScalarType.DOUBLE, Double::valueOf);
+ SCALARTYPE_FUNCTION_MAP.put(ScalarType.FLOAT_COMPLEX, FloatComplex::valueOf);
+ SCALARTYPE_FUNCTION_MAP.put(ScalarType.DOUBLE_COMPLEX, DoubleComplex::valueOf);
+ }
// ======================================================================
// Constructors
// ======================================================================
@@ -112,32 +130,10 @@
* @return The created {@code Value} with the converted value is returned.
*/
public Value getVirtualValue() {
- Function<String, Object> typeConverter;
-
ScalarType scalarType = getScalarType();
- if (scalarType.isString()) {
- typeConverter = v -> v;
- } else if (scalarType.isDate()) {
- typeConverter = v -> LocalDateTime.parse(v, Value.LOCAL_DATE_TIME_FORMATTER);
- } else if (scalarType.isBoolean()) {
- typeConverter = Boolean::valueOf;
- } else if (scalarType.isByte()) {
- typeConverter = Byte::valueOf;
- } else if (scalarType.isShort()) {
- typeConverter = Short::valueOf;
- } else if (scalarType.isInteger()) {
- typeConverter = Integer::valueOf;
- } else if (scalarType.isLong()) {
- typeConverter = Long::valueOf;
- } else if (scalarType.isFloat()) {
- typeConverter = Float::valueOf;
- } else if (scalarType.isDouble()) {
- typeConverter = Double::valueOf;
- } else if (scalarType.isFloatComplex()) {
- typeConverter = FloatComplex::valueOf;
- } else if (scalarType.isDoubleComplex()) {
- typeConverter = DoubleComplex::valueOf;
- } else {
+ Function<String, Object> typeConverter = SCALARTYPE_FUNCTION_MAP.get(scalarType);
+
+ if(typeConverter == null) {
return ValueType.UNKNOWN.create(getName());
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/Channel.java b/src/main/java/org/eclipse/mdm/api/base/model/Channel.java
index 15b121c..fefe47c 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/Channel.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/Channel.java
@@ -8,6 +8,8 @@
package org.eclipse.mdm.api.base.model;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of the channel entity type. Entities of this type are based on
* {@link Quantity}s.
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/ChannelGroup.java b/src/main/java/org/eclipse/mdm/api/base/model/ChannelGroup.java
index fbf5a8e..160ab2c 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/ChannelGroup.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/ChannelGroup.java
@@ -8,6 +8,8 @@
package org.eclipse.mdm.api.base.model;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of the channel group entity type. It belongs to exactly one
* {@link Measurement} and groups a set of its {@link Channel}s.
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/ContextComponent.java b/src/main/java/org/eclipse/mdm/api/base/model/ContextComponent.java
index cbf8a81..b4b7fb3 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/ContextComponent.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/ContextComponent.java
@@ -12,6 +12,8 @@
import java.util.Optional;
import java.util.stream.Collectors;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of the context component entity types. Instances of this class
* are only provided / managed via the owning descriptive {@link ContextRoot}.
@@ -66,6 +68,15 @@
}
/**
+ * Returns the {@link ContextRoot} this context component belongs to.
+ *
+ * @return The parent {@link ContextRoot}.
+ */
+ public ContextRoot getContextRoot() {
+ return getCore().getPermanentStore().get(ContextRoot.class);
+ }
+
+ /**
* Removes the {@link ContextSensor} identified by given name.
*
* @param name
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/ContextDescribable.java b/src/main/java/org/eclipse/mdm/api/base/model/ContextDescribable.java
index b3f5083..1337ee6 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/ContextDescribable.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/ContextDescribable.java
@@ -37,7 +37,7 @@
* @throws DataAccessException
* Thrown if unable to query the available {@code ContextType}s.
*/
- List<ContextType> loadContextTypes(BaseEntityManager<? extends BaseEntityFactory> manager) throws DataAccessException;
+ List<ContextType> loadContextTypes(BaseEntityManager manager) throws DataAccessException;
/**
* Loads the requested {@link ContextRoot}s for given
@@ -55,7 +55,7 @@
* ContextRoot}s.
* @see ContextType
*/
- Map<ContextType, ContextRoot> loadContexts(BaseEntityManager<? extends BaseEntityFactory> manager, ContextType... contextTypes)
+ Map<ContextType, ContextRoot> loadContexts(BaseEntityManager manager, ContextType... contextTypes)
throws DataAccessException;
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/ContextRoot.java b/src/main/java/org/eclipse/mdm/api/base/model/ContextRoot.java
index 4c7548f..d4fc3e9 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/ContextRoot.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/ContextRoot.java
@@ -15,6 +15,8 @@
import java.util.Optional;
import java.util.stream.Collectors;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of the context root entity types. This is the root node of the
* descriptive component structure for a {@link ContextType}. This element is
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/ContextSensor.java b/src/main/java/org/eclipse/mdm/api/base/model/ContextSensor.java
index 1f3f909..9c5b997 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/ContextSensor.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/ContextSensor.java
@@ -8,6 +8,8 @@
package org.eclipse.mdm.api.base.model;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of the context sensor entity types. Instances of this class
* are only provided / managed via the owning {@link ContextComponent}. A
@@ -33,4 +35,12 @@
super(core);
}
+ /**
+ * Returns the {@link ContextComponent} this context sensor belongs to.
+ *
+ * @return The parent {@link ContextComponent}
+ */
+ public ContextComponent getContextComponent() {
+ return getCore().getPermanentStore().get(ContextComponent.class);
+ }
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/Core.java b/src/main/java/org/eclipse/mdm/api/base/model/Core.java
deleted file mode 100644
index f45f66a..0000000
--- a/src/main/java/org/eclipse/mdm/api/base/model/Core.java
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Copyright (c) 2016 Gigatronik Ingolstadt GmbH
- * 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
- */
-
-package org.eclipse.mdm.api.base.model;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-/**
- * Provides access to the internals of any entity:
- *
- * <ul>
- * <li>name of the data source</li>
- * <li>name of the type</li>
- * <li>instance ID</li>
- * <li>values</li>
- * <li>added/removed file links</li>
- * <li>related entities</li>
- * <li>parent/child entities</li>
- * </ul>
- *
- * @since 1.0.0
- * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
- */
-public interface Core {
-
- // ======================================================================
- // Public methods
- // ======================================================================
-
- /**
- * Returns the name of the data source this entity was retrieved from.
- *
- * @return Name of the data source.
- */
- String getSourceName();
-
- /**
- * Returns the name of the entity type.
- *
- * @return Name of the entity type is returned.
- */
- String getTypeName();
-
- /**
- * Returns the instance ID or {@code 0} if this instance is not yet
- * persisted.
- *
- * @return The instance ID is returned.
- */
- String getID();
-
- /**
- * Sets an instance ID.
- *
- * @param instanceID
- * The new instance ID.
- */
- void setID(String instanceID);
-
- /**
- * Returns <i>all</i> {@link Value} containers of this entity.
- *
- * @return Values mapped by their name are returned.
- */
- Map<String, Value> getValues();
-
- /**
- * Hides {@link Value} containers whose name is contained in the given names
- * {@code Collection}.
- *
- * @param names
- * Names of the {@code Value} which shall be hidden.
- */
- void hideValues(Collection<String> names);
-
- /**
- * Returns <i>all</i> {@link Value} containers, including the hidden ones.
- *
- * @return All {@code Value} containers are returned.
- */
- Map<String, Value> getAllValues();
-
- /**
- * Returns all newly added {@link FileLink}.
- *
- * @return New {@code FileLink}s are returned.
- */
- default List<FileLink> getAddedFileLinks() {
- Predicate<FileLink> isRemote = FileLink::isRemote;
-
- List<FileLink> fileLinks = getValues().values().stream().filter(v -> v.getValueType().isFileLink())
- .filter(Value::isValid).map(v -> (FileLink) v.extract()).filter(isRemote.negate())
- .collect(Collectors.toList());
-
- List<Value> values = getValues().values().stream().filter(v -> v.getValueType().isFileLinkSequence())
- .filter(Value::isValid).collect(Collectors.toList());
-
- for (Value value : values) {
- Arrays.stream((FileLink[]) value.extract()).filter(isRemote.negate()).forEach(fileLinks::add);
- }
-
- return fileLinks;
- }
-
- /**
- * Returns all removed {@link FileLink}s.
- *
- * @return Removed {@code FileLink}s are returned.
- */
- default List<FileLink> getRemovedFileLinks() {
- Predicate<FileLink> isRemote = FileLink::isRemote;
-
- List<FileLink> fileLinks = getValues().values().stream().filter(v -> v.getValueType().isFileLink())
- .filter(Value::isModified).map(v -> (FileLink) v.extractInitial()).filter(Objects::nonNull)
- .filter(isRemote).collect(Collectors.toList());
-
- List<Value> values = getValues().values().stream().filter(v -> v.getValueType().isFileLinkSequence())
- .filter(Value::wasValid).filter(Value::isModified).collect(Collectors.toList());
-
- for (Value value : values) {
- List<FileLink> current = Arrays.asList((FileLink[]) value.extract());
- Arrays.stream((FileLink[]) value.extractInitial()).filter(fl -> !current.contains(fl))
- .forEach(fileLinks::add);
- }
-
- return fileLinks;
- }
-
- /**
- * Applies modifications made to the entity stores and {@link Value}
- * containers.
- */
- default void apply() {
- // apply removed mutable entities
- getMutableStore().apply();
-
- // apply removed children
- getChildrenStore().apply();
-
- // apply modified values
- getValues().values().stream().filter(Value::isModified).forEach(Value::apply);
- }
-
- /**
- * Returns the mutable {@link EntityStore}. This store holds related
- * entities of any kind.
- *
- * @return The mutable {@code EntityStore} is returned.
- */
- EntityStore getMutableStore();
-
- /**
- * Returns the permanent {@link EntityStore}. This store holds usually only
- * the related parent entity.
- *
- * @return The permanent {@code EntityStore} is returned.
- */
- EntityStore getPermanentStore();
-
- /**
- * Returns the {@link ChildrenStore}. This store holds related child
- * entities of any kind.
- *
- * @return The {@code ChildrenStore} is returned.
- */
- ChildrenStore getChildrenStore();
-
- // ======================================================================
- // Inner classes
- // ======================================================================
-
- /**
- * Holds related entities of any kind and keeps track of modifications.
- */
- public static final class EntityStore {
-
- // ======================================================================
- // Instance variables
- // ======================================================================
-
- private final Map<String, Entity> current = new HashMap<>(0);
- private final Map<String, Entity> removed = new HashMap<>(0);
-
- // ======================================================================
- // Public methods
- // ======================================================================
-
- /**
- * Returns current set of related entities.
- *
- * @return Returned {@code Collection} is unmodifiable.
- */
- public Collection<Entity> getCurrent() {
- return Collections.unmodifiableCollection(current.values());
- }
-
- /**
- * Returns current set of removed related entities.
- *
- * @return Returned {@code Collection} is unmodifiable.
- */
- public Collection<Entity> getRemoved() {
- return Collections.unmodifiableCollection(removed.values());
- }
-
- /**
- * Returns related entity identified by given entity class.
- *
- * @param <T>
- * The desired entity type.
- * @param entityClass
- * Used as identifier.
- * @return The related entity is returned or null of not defined.
- */
- public <T extends Entity> T get(Class<T> entityClass) {
- return get(entityClass.getSimpleName(), entityClass);
- }
-
- /**
- * Returns related entity identified by given entity class.
- *
- * @param <T>
- * The desired entity type.
- * @param relationName
- * The relation name the entity is referenced by.
- * @param entityClass
- * Used as identifier.
- * @return The related entity is returned or null of not defined.
- */
- public <T extends Entity> T get(String relationName, Class<T> entityClass) {
- return entityClass.cast(current.get(relationName));
- }
-
- /**
- * Replaces a related entity with the given one.
- *
- * @param entity
- * The new related entity.
- */
- public void set(Entity entity) {
- set(entity.getClass().getSimpleName(), entity);
- }
-
- /**
- * Replaces a related entity with the given one.
- *
- * @param name
- * The name of the relation the entity is referenced by.
- * @param entity
- * The new related entity.
- */
- public void set(String name, Entity entity) {
- Entity old = current.put(name, entity);
- if (old != null) {
- removed.put(name, old);
- }
- }
-
- /**
- * Removes a related entity for given entity class.
- *
- * @param entityClass
- * Used as identifier.
- */
- public void remove(Class<? extends Entity> entityClass) {
- String key = entityClass.getSimpleName();
- remove(key, entityClass);
- }
-
- /**
- * Removes a related entity for given relation name and entity class.
- *
- * @param name
- * The name of the relation the entity is referenced by.
- * @param entityClass
- * Used as identifier.
- */
- public void remove(String name, Class<? extends Entity> entityClass) {
- Entity old = current.remove(name);
- if (old != null) {
- removed.put(name, old);
- }
- }
-
- /**
- * Returns related entity identified by given entity class and
- * {@link ContextType}.
- *
- * @param <T>
- * The desired entity type.
- * @param entityClass
- * Used as identifier.
- * @param contextType
- * Used as identifier.
- * @return The related entity is returned or null of not defined.
- */
- public <T extends Entity> T get(Class<T> entityClass, ContextType contextType) {
- return entityClass.cast(current.get(createContextTypeKey(entityClass, contextType)));
- }
-
- /**
- * Replaces a related entity with the given one.
- *
- * @param entity
- * The new related entity.
- * @param contextType
- * Used as identifier.
- */
- public void set(Entity entity, ContextType contextType) {
- String key = createContextTypeKey(entity.getClass(), contextType);
- Entity old = current.put(key, entity);
- if (old != null) {
- removed.put(key, old);
- }
- }
-
- /**
- * Removes a related entity for given entity class and
- * {@link ContextType}.
- *
- * @param entityClass
- * Used as identifier.
- * @param contextType
- * Used as identifier.
- */
- public void remove(Class<? extends Entity> entityClass, ContextType contextType) {
- String key = createContextTypeKey(entityClass, contextType);
- Entity old = current.remove(key);
- if (old != null) {
- removed.put(key, old);
- }
- }
-
- // ======================================================================
- // Private methods
- // ======================================================================
-
- /**
- * Drops removed entities.
- */
- private void apply() {
- removed.clear();
- }
-
- /**
- * Generates a key from given entity class and {@link ContextType}.
- *
- * @param entityClass
- * Identifier part 1.
- * @param contextType
- * Identifier part 2.
- * @return A context type dependent key is returned.
- */
- private static String createContextTypeKey(Class<? extends Entity> entityClass, ContextType contextType) {
- return entityClass.getSimpleName() + '_' + contextType;
- }
-
- }
-
- /**
- * Holds related entities of any kind and keeps track of modifications.
- */
- public static final class ChildrenStore {
-
- // ======================================================================
- // Instance variables
- // ======================================================================
-
- private final Map<Class<? extends Deletable>, List<? extends Deletable>> current = new HashMap<>(0);
- private final Map<Class<? extends Deletable>, List<? extends Deletable>> removed = new HashMap<>(0);
-
- // ======================================================================
- // Public methods
- // ======================================================================
-
- /**
- * Returns current set of related children mapped by their type.
- *
- * @return Returned {@code Map} is unmodifiable.
- */
- public Map<Class<? extends Deletable>, List<? extends Deletable>> getCurrent() {
- return Collections.unmodifiableMap(current);
- }
-
- /**
- * Returns current set of removed related children mapped by their type.
- *
- * @return Returned {@code Map} is unmodifiable.
- */
- public Map<Class<? extends Deletable>, List<? extends Deletable>> getRemoved() {
- return Collections.unmodifiableMap(removed);
- }
-
- /**
- * Returns related child entities of given type.
- *
- * @param <T>
- * Desired entity type.
- * @param entityClass
- * Used as identifier.
- * @return Returned {@code List} is unmodifiable.
- */
- @SuppressWarnings("unchecked")
- public <T extends Deletable> List<T> get(Class<T> entityClass) {
- return Collections.unmodifiableList((List<T>) current.computeIfAbsent(entityClass, k -> new ArrayList<>()));
- }
-
- /**
- * Sorts the child entities with given {@code Comparator}.
- *
- * @param <T>
- * Desired entity type.
- * @param entityClass
- * Used as identifier.
- * @param comparator
- * Used for sorting.
- */
- @SuppressWarnings("unchecked")
- public <T extends Deletable> void sort(Class<T> entityClass, Comparator<? super T> comparator) {
- List<T> children = (List<T>) current.get(entityClass);
- if (children != null) {
- children.sort(comparator);
- }
- }
-
- /**
- * Adds given child entity.
- *
- * @param child
- * The new child.
- */
- @SuppressWarnings("unchecked")
- public void add(Deletable child) {
- removed.getOrDefault(child.getClass(), new ArrayList<>()).remove(child);
- ((List<Deletable>) current.computeIfAbsent(child.getClass(), k -> new ArrayList<>())).add(child);
- }
-
- /**
- * Removes given child entity.
- *
- * @param child
- * The child which will be removed.
- */
- @SuppressWarnings("unchecked")
- public void remove(Deletable child) {
- List<Deletable> children = (List<Deletable>) current.getOrDefault(child.getClass(), new ArrayList<>());
- if (children.remove(child) && child.getID() != null && child.getID().length() > 0) {
- ((List<Deletable>) removed.computeIfAbsent(child.getClass(), k -> new ArrayList<>())).add(child);
- }
- }
-
- // ======================================================================
- // Private methods
- // ======================================================================
-
- /**
- * Drops removed children.
- */
- private void apply() {
- removed.clear();
- }
-
- }
-
-}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/EnumRegistry.java b/src/main/java/org/eclipse/mdm/api/base/model/EnumRegistry.java
index a032f75..4f1af69 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/EnumRegistry.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/EnumRegistry.java
@@ -9,12 +9,13 @@
package org.eclipse.mdm.api.base.model;
import java.util.HashMap;
+import java.util.Map;
/**
* This singleton class registers globally available enumerations.
*
*/
-public class EnumRegistry {
+public final class EnumRegistry {
// singleton instance
private static final EnumRegistry instance = new EnumRegistry();
@@ -27,7 +28,7 @@
public static final String VERSION_STATE = "VersionState";
public static final String AXIS_TYPE = "AxisType";
- private HashMap<String, Enumeration<? extends EnumerationValue>> enumerations;
+ private Map<String, Enumeration<? extends EnumerationValue>> enumerations;
/**
* Constructor. Not called directly. Use getInstance() instead.
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/Enumeration.java b/src/main/java/org/eclipse/mdm/api/base/model/Enumeration.java
index f0a823e..1a9fb56 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/Enumeration.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/Enumeration.java
@@ -10,6 +10,7 @@
import java.lang.reflect.Field;
import java.util.HashMap;
+import java.util.Map;
/**
* A class which dynamically bundles enumeration values
@@ -17,17 +18,16 @@
* @param <E>
*/
public class Enumeration<E extends EnumerationValue> {
- public E ens = null;
- private HashMap<String, E> values;
+ private Map<String, E> values;
- private HashMap<E, String> revvalues;
+ private Map<E, String> revvalues;
- private HashMap<Integer, String> ordinals;
+ private Map<Integer, String> ordinals;
- private HashMap<String, Integer> revordinals;
+ private Map<String, Integer> revordinals;
- private int nextordinal;
+ private int maxordinal;
private String name;
@@ -45,7 +45,7 @@
*/
@SuppressWarnings("unchecked")
public Enumeration(Class<E> enumclass, String name) {
- this.nextordinal = 0;
+ this.maxordinal = 0;
this.values = new HashMap<>();
this.revvalues = new HashMap<>();
this.ordinals = new HashMap<>();
@@ -73,12 +73,7 @@
fname = field.getName();
((EnumerationValue) fieldObject).setName(fname);
}
- ((EnumerationValue) fieldObject).setOwner(this);
- values.put(fname, (E) fieldObject);
- revvalues.put((E) fieldObject, fname);
- ordinals.put(nextordinal, fname);
- revordinals.put(fname, nextordinal);
- nextordinal++;
+ addValue((E) fieldObject);
}
}
}
@@ -90,12 +85,18 @@
*/
public void addValue(E enumeration) {
enumeration.setOwner(this);
- String name = enumeration.name();
- int ordinal = enumeration.ordinal();
- values.put(name, enumeration);
- revvalues.put(enumeration, name);
- ordinals.put(ordinal, name);
- revordinals.put(name, ordinal);
+ String enumerationName = enumeration.name();
+ Integer ordinal = enumeration.ordinal();
+ if (ordinal == null) {
+ ordinal = ++maxordinal;
+ enumeration.setOrdinal(ordinal);
+ } else {
+ maxordinal = Math.max(ordinal, maxordinal);
+ }
+ values.put(enumerationName, enumeration);
+ revvalues.put(enumeration, enumerationName);
+ ordinals.put(ordinal, enumerationName);
+ revordinals.put(enumerationName, ordinal);
}
/**
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/EnumerationValue.java b/src/main/java/org/eclipse/mdm/api/base/model/EnumerationValue.java
index 2c6e39d..dc5e799 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/EnumerationValue.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/EnumerationValue.java
@@ -17,8 +17,8 @@
* fields whose type is of the derivative class.
*
* To be able to add dynamically enum values and for full initialization, you
- * should set an owner enumeration (either by choosing the right
- * constructor or by calling the setOwner method)
+ * should set an owner enumeration (either by choosing the right constructor or
+ * by calling the setOwner method)
*
* @author Florian Schmitt
*
@@ -40,6 +40,15 @@
}
/**
+ * explicitly set the ordinal of this element.
+ *
+ * @param name
+ */
+ protected void setOrdinal(int ordinal) {
+ this.ordinal = ordinal;
+ }
+
+ /**
*
* set the owner dynamic enumeration of this object.
*
@@ -54,7 +63,6 @@
*
* @return
*/
- @SuppressWarnings("rawtypes")
public Enumeration<? extends EnumerationValue> getOwner() {
return owner;
}
@@ -77,8 +85,8 @@
*
* be sure to initialize the enumeration fully, by either adding it as a
* static field in an extending class, or setting the ordinal by hand.
- * You'll also have to add the resulting object to a DynamiEnumeration for
- * it to be completely usable.
+ * You'll also have to add the resulting object to a Enumeration for it to
+ * be completely usable.
*
* @param name
*/
@@ -89,8 +97,8 @@
/**
* This Constructor is protected to avoid accidental misuse.
*
- * You'll have to add the resulting object to a DynamiEnumeration for it to
- * be completely usable.
+ * You'll have to add the resulting object to a Enumeration for it to be
+ * completely usable.
*
* @param name
*/
@@ -101,6 +109,20 @@
}
/**
+ * This Constructor is protected to avoid accidental misuse.
+ *
+ * be sure to initialize the enumeration fully, by either adding it as a
+ * static field in an extending class, or setting the name by hand and
+ * adding the resulting object to a Enumeration for it to be completely
+ * usable.
+ *
+ * @param name
+ */
+ protected EnumerationValue(int ordinal) {
+ this(null, ordinal);
+ }
+
+ /**
* @return the name of this enumeration value
*/
public String name() {
@@ -118,11 +140,7 @@
* @return the ordinal value represented by this enumeration value
*/
public Integer ordinal() {
- if (this.ordinal != null) {
- return this.ordinal;
- } else {
- return owner.ordinal(this);
- }
+ return ordinal;
}
/*
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/Environment.java b/src/main/java/org/eclipse/mdm/api/base/model/Environment.java
index 8220e4e..3580700 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/Environment.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/Environment.java
@@ -8,6 +8,8 @@
package org.eclipse.mdm.api.base.model;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of the environment entity type. The {@link Environment} is a
* singleton within a connected data source.
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/FileLink.java b/src/main/java/org/eclipse/mdm/api/base/model/FileLink.java
index 433d5d1..32e7f2c 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/FileLink.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/FileLink.java
@@ -307,9 +307,14 @@
@Override
public int hashCode() {
if (State.LOCAL == state) {
+ if (!isLocal()) {
+ return "".hashCode();
+ }
return getLocalPath().hashCode();
}
-
+ if (!isRemote()) {
+ return "".hashCode();
+ }
return getRemotePath().hashCode();
}
@@ -322,9 +327,14 @@
FileLink other = (FileLink) object;
if (state == other.state) {
if (State.LOCAL == state) {
+ if (!isLocal()) {
+ return !other.isLocal();
+ }
return getLocalPath().equals(other.getLocalPath());
}
-
+ if (!isRemote()) {
+ return !other.isRemote();
+ }
return getRemotePath().equals(other.getRemotePath());
}
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/Interpolation.java b/src/main/java/org/eclipse/mdm/api/base/model/Interpolation.java
index 932db5f..7ea14fb 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/Interpolation.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/Interpolation.java
@@ -17,28 +17,20 @@
*/
public class Interpolation extends EnumerationValue {
- // ======================================================================
- // Enumerations
- // ======================================================================
-
/**
* No interpolation is used.
*/
- public static final Interpolation NONE = new Interpolation();
+ public static final Interpolation NONE = new Interpolation(0);
/**
* Interpolation is linear.
*/
- public static final Interpolation LINEAR = new Interpolation();
+ public static final Interpolation LINEAR = new Interpolation(1);
/**
* Interpolation is application specific.
*/
- public static final Interpolation SPECIFIC = new Interpolation();
-
- // ======================================================================
- // Public methods
- // ======================================================================
+ public static final Interpolation SPECIFIC = new Interpolation(2);
/**
* Returns true if this interpolation is {@link #NONE}.
@@ -70,4 +62,11 @@
return SPECIFIC == this;
}
+ /**
+ * Constructor, sets the order
+ */
+ Interpolation(int ord) {
+ super(ord);
+ }
+
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/MeasuredValues.java b/src/main/java/org/eclipse/mdm/api/base/model/MeasuredValues.java
index a93c90e..7f455b2 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/MeasuredValues.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/MeasuredValues.java
@@ -12,6 +12,7 @@
import static org.eclipse.mdm.api.base.model.Value.readAt;
import java.lang.reflect.Array;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;
@@ -77,7 +78,7 @@
throw new IllegalArgumentException("Length of values and flags is not equal.");
}
- this.flags = flags;
+ this.flags = Arrays.copyOf(flags, flags.length);
length = flags.length;
}
@@ -144,26 +145,22 @@
// idea: getScalarType().createIterator(values, flags); // <- package
// private
return new ValueIterator<E>() {
-
private int index = 0;
@Override
public boolean hasNext() {
return index < length;
}
-
@Override
public boolean isValid() {
return flags[index];
}
-
@Override
@SuppressWarnings("unchecked")
public E next() {
if (hasNext()) {
return (E) Array.get(values, index++);
}
-
throw new NoSuchElementException("Subsequent value is not available.");
}
};
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/Measurement.java b/src/main/java/org/eclipse/mdm/api/base/model/Measurement.java
index 4a0bad0..f6ded11 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/Measurement.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/Measurement.java
@@ -13,6 +13,7 @@
import java.util.Map;
import org.eclipse.mdm.api.base.BaseEntityManager;
+import org.eclipse.mdm.api.base.adapter.Core;
import org.eclipse.mdm.api.base.query.DataAccessException;
/**
@@ -136,7 +137,7 @@
* {@inheritDoc}
*/
@Override
- public List<ContextType> loadContextTypes(BaseEntityManager<? extends BaseEntityFactory> manager)
+ public List<ContextType> loadContextTypes(BaseEntityManager manager)
throws DataAccessException {
return manager.loadContextTypes(this);
}
@@ -145,7 +146,7 @@
* {@inheritDoc}
*/
@Override
- public Map<ContextType, ContextRoot> loadContexts(BaseEntityManager<? extends BaseEntityFactory> manager,
+ public Map<ContextType, ContextRoot> loadContexts(BaseEntityManager manager,
ContextType... contextTypes) throws DataAccessException {
return manager.loadContexts(this, contextTypes);
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/Parameter.java b/src/main/java/org/eclipse/mdm/api/base/model/Parameter.java
index 3845655..c9def26 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/Parameter.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/Parameter.java
@@ -10,6 +10,8 @@
import java.time.LocalDateTime;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of the parameter entity type. Instances of this class hold a
* value in its {@code String} representation, which is converted upon request
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/ParameterSet.java b/src/main/java/org/eclipse/mdm/api/base/model/ParameterSet.java
index 178891d..df38cb8 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/ParameterSet.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/ParameterSet.java
@@ -12,6 +12,8 @@
import java.util.Optional;
import java.util.stream.Collectors;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of the parameter set entity type. Instances of this class
* group a set of further describing data stored in {@link Parameter}s.
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/PhysicalDimension.java b/src/main/java/org/eclipse/mdm/api/base/model/PhysicalDimension.java
index c0068b3..2a257c9 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/PhysicalDimension.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/PhysicalDimension.java
@@ -8,6 +8,8 @@
package org.eclipse.mdm.api.base.model;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of the physical dimension entity type. Each {@link Unit} must
* have a relation to an instance of this type. The attributes represent the
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/Quantity.java b/src/main/java/org/eclipse/mdm/api/base/model/Quantity.java
index 4ed5d6e..28c945a 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/Quantity.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/Quantity.java
@@ -8,6 +8,8 @@
package org.eclipse.mdm.api.base.model;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of the quantity entity type. {@link Channel}s are based on
* entities of this type. Each quantity has a relation to a default
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/ScalarType.java b/src/main/java/org/eclipse/mdm/api/base/model/ScalarType.java
index 170ff36..ac0fe95 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/ScalarType.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/ScalarType.java
@@ -22,9 +22,7 @@
* @author Sebastian Dirsch, Gigatronik Ingolstadt GmbH
*/
-
-
-public class ScalarType extends EnumerationValue {
+public final class ScalarType extends EnumerationValue {
// ======================================================================
// Enumerations
@@ -34,96 +32,98 @@
* A {@link MeasuredValues} with this type contains an array sequence of
* {@code String} values.
*/
- public static final ScalarType STRING = new ScalarType(ValueType.STRING_SEQUENCE, String.class);
+ public static final ScalarType STRING = new ScalarType(0, ValueType.STRING_SEQUENCE, String.class);
/**
* A {@link MeasuredValues} with this type contains an array sequence of
* {@code LocalDateTime} values.
*/
- public static final ScalarType DATE = new ScalarType(ValueType.DATE_SEQUENCE, LocalDateTime.class);
+ public static final ScalarType DATE = new ScalarType(1, ValueType.DATE_SEQUENCE, LocalDateTime.class);
/**
* A {@link MeasuredValues} with this type contains an array sequence of
* {@code boolean} values.
*/
- public static final ScalarType BOOLEAN = new ScalarType(ValueType.BOOLEAN_SEQUENCE, boolean.class);
+ public static final ScalarType BOOLEAN = new ScalarType(2, ValueType.BOOLEAN_SEQUENCE, boolean.class);
/**
* A {@link MeasuredValues} with this type contains an array sequence of
* {@code byte} values.
*/
- public static final ScalarType BYTE = new ScalarType(ValueType.BYTE_SEQUENCE, byte.class);
+ public static final ScalarType BYTE = new ScalarType(3, ValueType.BYTE_SEQUENCE, byte.class);
/**
* A {@link MeasuredValues} with this type contains an array sequence of
* {@code short} values.
*/
- public static final ScalarType SHORT = new ScalarType(ValueType.SHORT_SEQUENCE, short.class);
+ public static final ScalarType SHORT = new ScalarType(4, ValueType.SHORT_SEQUENCE, short.class);
/**
* A {@link MeasuredValues} with this type contains an array sequence of
* {@code int} values.
*/
- public static final ScalarType INTEGER = new ScalarType(ValueType.INTEGER_SEQUENCE, int.class);
+ public static final ScalarType INTEGER = new ScalarType(5, ValueType.INTEGER_SEQUENCE, int.class);
/**
* A {@link MeasuredValues} with this type contains an array sequence of
* {@code long} values.
*/
- public static final ScalarType LONG = new ScalarType(ValueType.LONG_SEQUENCE, long.class);
+ public static final ScalarType LONG = new ScalarType(6, ValueType.LONG_SEQUENCE, long.class);
/**
* A {@link MeasuredValues} with this type contains an array sequence of
* {@code float} values.
*/
- public static final ScalarType FLOAT = new ScalarType(ValueType.FLOAT_SEQUENCE, float.class);
+ public static final ScalarType FLOAT = new ScalarType(7, ValueType.FLOAT_SEQUENCE, float.class);
/**
* A {@link MeasuredValues} with this type contains an array sequence of
* {@code double} values.
*/
- public static final ScalarType DOUBLE = new ScalarType(ValueType.DOUBLE_SEQUENCE, double.class);
+ public static final ScalarType DOUBLE = new ScalarType(8, ValueType.DOUBLE_SEQUENCE, double.class);
/**
* A {@link MeasuredValues} with this type contains an array sequence of
* {@code byte[]} values.
*/
- public static final ScalarType BYTE_STREAM = new ScalarType(ValueType.BYTE_STREAM_SEQUENCE, byte[].class);
+ public static final ScalarType BYTE_STREAM = new ScalarType(9, ValueType.BYTE_STREAM_SEQUENCE, byte[].class);
/**
* A {@link MeasuredValues} with this type contains an array sequence of
* {@code FloatComplex} values.
*/
- public static final ScalarType FLOAT_COMPLEX = new ScalarType(ValueType.FLOAT_COMPLEX_SEQUENCE, FloatComplex.class);
+ public static final ScalarType FLOAT_COMPLEX = new ScalarType(10, ValueType.FLOAT_COMPLEX_SEQUENCE,
+ FloatComplex.class);
/**
* A {@link MeasuredValues} with this type contains an array sequence of
* {@code DoubleComplex} values.
*/
- public static final ScalarType DOUBLE_COMPLEX = new ScalarType(ValueType.DOUBLE_COMPLEX_SEQUENCE, DoubleComplex.class);
+ public static final ScalarType DOUBLE_COMPLEX = new ScalarType(11, ValueType.DOUBLE_COMPLEX_SEQUENCE,
+ DoubleComplex.class);
/**
* {@link MeasuredValues} are not allowed to be of this type. This constant
* may be used in other contexts.
*/
- public static final ScalarType ENUMERATION = new ScalarType(ValueType.ENUMERATION_SEQUENCE);
+ public static final ScalarType ENUMERATION = new ScalarType(12, ValueType.ENUMERATION_SEQUENCE);
/**
* A {@link MeasuredValues} with this type contains an array sequence of
* {@code FileLink} values.
*/
- public static final ScalarType FILE_LINK = new ScalarType(ValueType.FILE_LINK_SEQUENCE, FileLink.class);
+ public static final ScalarType FILE_LINK = new ScalarType(13, ValueType.FILE_LINK_SEQUENCE, FileLink.class);
/**
* TODO ...
*/
- public static final ScalarType BLOB = new ScalarType(ValueType.BLOB, Object.class);
+ public static final ScalarType BLOB = new ScalarType(14, ValueType.BLOB, Object.class);
/**
* {@link MeasuredValues} are not allowed to be of this type. This constant
* may be used in other contexts.
*/
- public static final ScalarType UNKNOWN = new ScalarType(ValueType.UNKNOWN);
+ public static final ScalarType UNKNOWN = new ScalarType(15, ValueType.UNKNOWN);
// ======================================================================
// Instance variables
@@ -142,7 +142,8 @@
* @param valueType
* The associated {@link ValueType}.
*/
- private ScalarType(ValueType valueType) {
+ private ScalarType(int ord, ValueType valueType) {
+ super(ord);
this.valueType = valueType;
arrayType = null;
}
@@ -156,7 +157,8 @@
* The component type of the array held by instances of
* {@link MeasuredValues}.
*/
- private ScalarType(ValueType valueType, Class<?> componentType) {
+ private ScalarType(int ord, ValueType valueType, Class<?> componentType) {
+ super(ord);
this.valueType = valueType;
arrayType = Array.newInstance(componentType, 0).getClass();
}
@@ -434,5 +436,4 @@
public ValueType toSingleValueType() {
return valueType.toSingleType();
}
-
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/SequenceRepresentation.java b/src/main/java/org/eclipse/mdm/api/base/model/SequenceRepresentation.java
index 7a45464..48579a8 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/SequenceRepresentation.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/SequenceRepresentation.java
@@ -26,14 +26,14 @@
* Measured values are stored as is and values are therefore immediately
* available.
*/
- public static final SequenceRepresentation EXPLICIT = new SequenceRepresentation();
+ public static final SequenceRepresentation EXPLICIT = new SequenceRepresentation(0);
/**
* Each value x<sub>i</sub> is generated as follows: x<sub>i</sub> = p for i
* ∈ [1, n], n is the total number of values and generation parameter p
* (offset).
*/
- public static final SequenceRepresentation IMPLICIT_CONSTANT = new SequenceRepresentation();
+ public static final SequenceRepresentation IMPLICIT_CONSTANT = new SequenceRepresentation(1);
/**
* Each value x<sub>i</sub> is generated as follows: x<sub>i</sub> =
@@ -41,7 +41,7 @@
* number of values and generation parameters p<sub>1</sub> (start value)
* and p<sub>2</sub> (increment).
*/
- public static final SequenceRepresentation IMPLICIT_LINEAR = new SequenceRepresentation();
+ public static final SequenceRepresentation IMPLICIT_LINEAR = new SequenceRepresentation(2);
/**
* Each value x<sub>i</sub> is generated as follows: x<sub>i</sub> =
@@ -52,7 +52,7 @@
* (p<sub>3</sub>-p<sub>1</sub>)/p<sub>2</sub> must be truncated to integer
* to start each saw curve cycle at p<sub>1</sub>.
*/
- public static final SequenceRepresentation IMPLICIT_SAW = new SequenceRepresentation();
+ public static final SequenceRepresentation IMPLICIT_SAW = new SequenceRepresentation(3);
/**
* Each value x<sub>i</sub> is generated as follows: x<sub>i</sub> =
@@ -60,7 +60,7 @@
* total number of values and generation parameters p<sub>1</sub> (offset),
* p<sub>2</sub> (factor) and the raw value r at position i.
*/
- public static final SequenceRepresentation RAW_LINEAR = new SequenceRepresentation();
+ public static final SequenceRepresentation RAW_LINEAR = new SequenceRepresentation(4);
/**
* Each value x<sub>i</sub> is generated as follows: x<sub>i</sub> = ∑
@@ -70,18 +70,19 @@
* p<sub>j</sub> for j ∈ [1, p<sub>1</sub>] and the raw value r at
* position i.
*/
- public static final SequenceRepresentation RAW_POLYNOMIAL = new SequenceRepresentation();
+ public static final SequenceRepresentation RAW_POLYNOMIAL = new SequenceRepresentation(5);
/*
- * Not used. Do not remove, because this changes the ordinal numbers of the enumeration.
+ * Not used. Do not remove, because this changes the ordinal numbers of the
+ * enumeration.
*/
- public static final SequenceRepresentation FORMULA = new SequenceRepresentation();
-
+ public static final SequenceRepresentation FORMULA = new SequenceRepresentation(6);
+
/**
* Measured values are stored as is in an external file and values are
* therefore immediately available.
*/
- public static final SequenceRepresentation EXPLICIT_EXTERNAL = new SequenceRepresentation();
+ public static final SequenceRepresentation EXPLICIT_EXTERNAL = new SequenceRepresentation(7);
/**
* Each value x<sub>i</sub> is generated as follows: x<sub>i</sub> =
@@ -90,7 +91,7 @@
* p<sub>2</sub> (factor) and the raw value r at position i read from an
* external file.
*/
- public static final SequenceRepresentation RAW_LINEAR_EXTERNAL = new SequenceRepresentation();
+ public static final SequenceRepresentation RAW_LINEAR_EXTERNAL = new SequenceRepresentation(8);
/**
* Each value x<sub>i</sub> is generated as follows: x<sub>i</sub> = ∑
@@ -100,7 +101,7 @@
* p<sub>j</sub> for j ∈ [1, p<sub>1</sub>] and the raw value r at
* position i read from an external file.
*/
- public static final SequenceRepresentation RAW_POLYNOMIAL_EXTERNAL = new SequenceRepresentation();
+ public static final SequenceRepresentation RAW_POLYNOMIAL_EXTERNAL = new SequenceRepresentation(9);
/**
* Each value x<sub>i</sub> is generated as follows: x<sub>i</sub> =
@@ -109,7 +110,7 @@
* p<sub>1</sub> (offset), p<sub>2</sub> (factor), p<sub>2</sub>
* (calibration) and the raw value r at position i.
*/
- public static final SequenceRepresentation RAW_LINEAR_CALIBRATED = new SequenceRepresentation();
+ public static final SequenceRepresentation RAW_LINEAR_CALIBRATED = new SequenceRepresentation(10);
/**
* Each value x<sub>i</sub> is generated as follows: x<sub>i</sub> =
@@ -119,7 +120,7 @@
* (calibration) and the raw value r at position i read from an external
* file.
*/
- public static final SequenceRepresentation RAW_LINEAR_CALIBRATED_EXTERNAL = new SequenceRepresentation();
+ public static final SequenceRepresentation RAW_LINEAR_CALIBRATED_EXTERNAL = new SequenceRepresentation(11);
// ======================================================================
// Public methods
@@ -246,4 +247,10 @@
return name().startsWith("RAW");
}
+ /**
+ * Constructor, ensures the correct order
+ */
+ SequenceRepresentation(int ord) {
+ super(ord);
+ }
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/Test.java b/src/main/java/org/eclipse/mdm/api/base/model/Test.java
index 828a88c..03f527a 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/Test.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/Test.java
@@ -11,6 +11,8 @@
import java.util.List;
import java.util.Optional;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of the test entity type. The test groups a number of single
* {@link TestStep}s. A measurement order always corresponds with exactly one
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/TestStep.java b/src/main/java/org/eclipse/mdm/api/base/model/TestStep.java
index 802c220..b6a80f9 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/TestStep.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/TestStep.java
@@ -12,6 +12,7 @@
import java.util.Map;
import org.eclipse.mdm.api.base.BaseEntityManager;
+import org.eclipse.mdm.api.base.adapter.Core;
import org.eclipse.mdm.api.base.query.DataAccessException;
/**
@@ -94,7 +95,7 @@
* {@inheritDoc}
*/
@Override
- public List<ContextType> loadContextTypes(BaseEntityManager<? extends BaseEntityFactory> manager)
+ public List<ContextType> loadContextTypes(BaseEntityManager manager)
throws DataAccessException {
return manager.loadContextTypes(this);
}
@@ -103,7 +104,7 @@
* {@inheritDoc}
*/
@Override
- public Map<ContextType, ContextRoot> loadContexts(BaseEntityManager<? extends BaseEntityFactory> manager,
+ public Map<ContextType, ContextRoot> loadContexts(BaseEntityManager manager,
ContextType... contextTypes) throws DataAccessException {
return manager.loadContexts(this, contextTypes);
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/TypeSpecification.java b/src/main/java/org/eclipse/mdm/api/base/model/TypeSpecification.java
index 9c8dd6c..8d24763 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/TypeSpecification.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/TypeSpecification.java
@@ -22,80 +22,86 @@
// Enumerations
// ======================================================================
- final static TypeSpecification BOOLEAN = new TypeSpecification();
+ final static TypeSpecification BOOLEAN = new TypeSpecification(0);
- final static TypeSpecification BYTE = new TypeSpecification();
+ final static TypeSpecification BYTE = new TypeSpecification(1);
- final static TypeSpecification SHORT = new TypeSpecification();
+ final static TypeSpecification SHORT = new TypeSpecification(2);
- final static TypeSpecification INTEGER = new TypeSpecification();
+ final static TypeSpecification INTEGER = new TypeSpecification(3);
- final static TypeSpecification LONG = new TypeSpecification();
+ final static TypeSpecification LONG = new TypeSpecification(4);
- final static TypeSpecification FLOAT = new TypeSpecification();
+ final static TypeSpecification FLOAT = new TypeSpecification(5);
- final static TypeSpecification DOUBLE = new TypeSpecification();
+ final static TypeSpecification DOUBLE = new TypeSpecification(6);
- final static TypeSpecification SHORT_BEO = new TypeSpecification();
+ final static TypeSpecification SHORT_BEO = new TypeSpecification(7);
- final static TypeSpecification INTEGER_BEO = new TypeSpecification();
+ final static TypeSpecification INTEGER_BEO = new TypeSpecification(8);
- final static TypeSpecification LONG_BEO = new TypeSpecification();
+ final static TypeSpecification LONG_BEO = new TypeSpecification(9);
- final static TypeSpecification FLOAT_BEO = new TypeSpecification();
+ final static TypeSpecification FLOAT_BEO = new TypeSpecification(10);
- final static TypeSpecification DOUBLE_BEO = new TypeSpecification();
+ final static TypeSpecification DOUBLE_BEO = new TypeSpecification(11);
- final static TypeSpecification STRING = new TypeSpecification();
+ final static TypeSpecification STRING = new TypeSpecification(12);
- final static TypeSpecification BYTE_STREAM = new TypeSpecification();
+ final static TypeSpecification BYTE_STREAM = new TypeSpecification(13);
- final static TypeSpecification BLOB = new TypeSpecification();
+ final static TypeSpecification BLOB = new TypeSpecification(14);
- final static TypeSpecification BOOLEAN_FLAGS_BEO = new TypeSpecification();
+ final static TypeSpecification BOOLEAN_FLAGS_BEO = new TypeSpecification(15);
- final static TypeSpecification BYTE_FLAGS_BEO = new TypeSpecification();
+ final static TypeSpecification BYTE_FLAGS_BEO = new TypeSpecification(16);
- final static TypeSpecification STRING_FLAGS_BEO = new TypeSpecification();
+ final static TypeSpecification STRING_FLAGS_BEO = new TypeSpecification(17);
- final static TypeSpecification BYTE_STREAM_BEO = new TypeSpecification();
+ final static TypeSpecification BYTE_STREAM_BEO = new TypeSpecification(18);
// SBYTE,
- final static TypeSpecification SIGNED_BYTE = new TypeSpecification();
+ final static TypeSpecification SIGNED_BYTE = new TypeSpecification(19);
// SBYTE_FLAGS_BEO,
- final static TypeSpecification SIGNED_BYTE_FLAGS_BEO = new TypeSpecification();
+ final static TypeSpecification SIGNED_BYTE_FLAGS_BEO = new TypeSpecification(20);
// USHORT,
- final static TypeSpecification UNSIGNED_SHORT = new TypeSpecification();
+ final static TypeSpecification UNSIGNED_SHORT = new TypeSpecification(21);
// USHORT_BEO,
- final static TypeSpecification UNSIGNED_SHORT_BEO = new TypeSpecification();
+ final static TypeSpecification UNSIGNED_SHORT_BEO = new TypeSpecification(22);
// UINTEGER,
- final static TypeSpecification UNSIGNED_INTEGER = new TypeSpecification();
+ final static TypeSpecification UNSIGNED_INTEGER = new TypeSpecification(23);
// UINTEGER_BEO,
- final static TypeSpecification UNSIGNED_INTEGER_BEO = new TypeSpecification();
+ final static TypeSpecification UNSIGNED_INTEGER_BEO = new TypeSpecification(24);
- final static TypeSpecification STRING_UTF8 = new TypeSpecification();
+ final static TypeSpecification STRING_UTF8 = new TypeSpecification(25);
- final static TypeSpecification STRING_UTF8_FLAGS_BEO = new TypeSpecification();
+ final static TypeSpecification STRING_UTF8_FLAGS_BEO = new TypeSpecification(26);
// BIT_INT,
- final static TypeSpecification BIT_INTEGER = new TypeSpecification();
+ final static TypeSpecification BIT_INTEGER = new TypeSpecification(27);
// BIT_INT_BEO,
- final static TypeSpecification BIT_INTEGER_BEO = new TypeSpecification();
+ final static TypeSpecification BIT_INTEGER_BEO = new TypeSpecification(28);
// BIT_UINT,
- final static TypeSpecification BIT_UNSIGNED_INTEGER = new TypeSpecification();
+ final static TypeSpecification BIT_UNSIGNED_INTEGER = new TypeSpecification(29);
// BIT_UINT_BEO,
- final static TypeSpecification BIT_UNSIGNED_INTEGER_BEO = new TypeSpecification();
+ final static TypeSpecification BIT_UNSIGNED_INTEGER_BEO = new TypeSpecification(30);
- final static TypeSpecification BIT_FLOAT = new TypeSpecification();
+ final static TypeSpecification BIT_FLOAT = new TypeSpecification(31);
- final static TypeSpecification BIT_FLOAT_BEO = new TypeSpecification();
+ final static TypeSpecification BIT_FLOAT_BEO = new TypeSpecification(32);
+ /**
+ * Constructor, sets the order
+ */
+ TypeSpecification(int ord) {
+ super(ord);
+ }
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/Unit.java b/src/main/java/org/eclipse/mdm/api/base/model/Unit.java
index 1c6b49f..c14a368 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/Unit.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/Unit.java
@@ -8,6 +8,8 @@
package org.eclipse.mdm.api.base.model;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of the unit entity type. Units referring to the same
* {@link PhysicalDimension} can be converted to each other by means of their
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/User.java b/src/main/java/org/eclipse/mdm/api/base/model/User.java
index 86cae4d..ba0f705 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/User.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/User.java
@@ -8,6 +8,8 @@
package org.eclipse.mdm.api.base.model;
+import org.eclipse.mdm.api.base.adapter.Core;
+
/**
* Implementation of the user entity type.
*
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/Value.java b/src/main/java/org/eclipse/mdm/api/base/model/Value.java
index 05ee859..87abf10 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/Value.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/Value.java
@@ -211,21 +211,7 @@
value = input;
setValid(true);
} else if (input instanceof EnumerationValue) {
- String inpvalueTypeDescr = ((EnumerationValue)input).getOwner().getName();
- if (inpvalueTypeDescr==null) {
- throw new IllegalArgumentException("EnumerationValue value description of input value not correctly initialized");
- }
- if (valueTypeDescr==null)
- throw new IllegalArgumentException("EnumerationValue value description not correctly initialized got null, '"
- + "' expected '" + valueClass.getSimpleName() + "'.");
-
- if (valueTypeDescr.equals(inpvalueTypeDescr)){
- value=input;
- setValid(true);
- } else {
- throw new IllegalArgumentException("Incompatible value type description'" + inpvalueTypeDescr
- + "' passed, expected '" + valueTypeDescr + "'.");
- }
+ setForEnumerationValue(input);
} else {
throw new IllegalArgumentException("Incompatible value type '" + input.getClass().getSimpleName()
+ "' passed, expected '" + valueClass.getSimpleName() + "'.");
@@ -258,6 +244,42 @@
return new Value(this, equalValue && bothValid ? extract() : null);
}
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof Value)) {
+ return false;
+ }
+
+ Value value = (Value) other;
+
+ return Objects.equals(this.valueType, value.valueType)
+ && Objects.equals(this.name, value.name)
+ && Objects.equals(this.unit, value.unit)
+ && Objects.equals(this.initialValid, value.initialValid)
+ && Objects.deepEquals(this.initialValue, value.initialValue)
+ && Objects.equals(this.valid, value.valid)
+ && Objects.deepEquals(this.value, value.value)
+ && Objects.equals(this.valueClass, value.valueClass)
+ && Objects.equals(this.valueTypeDescr, value.valueTypeDescr)
+ && Objects.equals(this.defaultValue, value.defaultValue);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(valueType, name, unit, initialValid, initialValue, valid, value, valueClass, valueTypeDescr, defaultValue);
+ }
+
/**
* Returns a human readable {@code String} representation of this value. In
* case of a sequence value container with up to 10 values the complete
@@ -297,10 +319,6 @@
return sb.toString();
}
- // ======================================================================
- // Package methods
- // ======================================================================
-
/**
* Checks whether either the validity flag or the value have been modified
* since initialization.
@@ -308,7 +326,7 @@
* @return Returns {@code true} either if the flag or the value has been
* modified.
*/
- boolean isModified() {
+ public boolean isModified() {
return wasValid() != isValid() || !Objects.deepEquals(extractInitial(), extract());
}
@@ -317,7 +335,7 @@
*
* @return Returns {@code true} if the value was initially marked as valid.
*/
- boolean wasValid() {
+ public boolean wasValid() {
return initialValid;
}
@@ -326,17 +344,21 @@
*
* @return The initial value is returned.
*/
- Object extractInitial() {
+ public Object extractInitial() {
return initialValue;
}
/**
* Overwrites the initial validity flag and value with the current ones.
*/
- void apply() {
+ public void apply() {
initialValid = isValid();
initialValue = copy(extract());
}
+
+ // ======================================================================
+ // Package methods
+ // ======================================================================
/**
* Returns the {@code String} value from given array at given position.
@@ -375,20 +397,7 @@
Class<?> valueClass = value.getClass();
if (valueClass.isArray() && Array.getLength(value) > 0) {
- int length = Array.getLength(value);
- if (valueClass.getComponentType().isPrimitive()) {
- Object copy = Array.newInstance(valueClass.getComponentType(), length);
- System.arraycopy(value, 0, copy, 0, length);
- return copy;
- } else {
- if (value instanceof byte[][]) {
- return Arrays.stream((byte[][]) value).map(v -> v.clone()).toArray(byte[][]::new);
- } else if (value instanceof FileLink[]) {
- return Arrays.stream((FileLink[]) value).map(FileLink::new).toArray(FileLink[]::new);
- } else {
- return Arrays.copyOf((Object[]) value, length);
- }
- }
+ return createDeepCopy(value, valueClass);
} else if (value instanceof FileLink) {
return new FileLink((FileLink) value);
}
@@ -396,5 +405,62 @@
// simple immutable value
return value;
}
+
+ /**
+ * Replaces currently stored value with the given one.
+ *
+ * @param input
+ * The new value must be an instance of the enumeration type
+ * an appropriate enumeration constant.
+ * @throws IllegalArgumentException
+ * Thrown if an incompatible value is given.
+ */
+ private void setForEnumerationValue(Object input) {
+ String inpvalueTypeDescr = ((EnumerationValue) input).getOwner().getName();
+ if (inpvalueTypeDescr == null) {
+ throw new IllegalArgumentException(
+ "EnumerationValue value description of input value not correctly initialized");
+ }
+ if (valueTypeDescr == null) {
+ throw new IllegalArgumentException(
+ "EnumerationValue value description not correctly initialized got null, '" + "' expected '"
+ + valueClass.getSimpleName() + "'.");
+ }
+ if (valueTypeDescr.equals(inpvalueTypeDescr)) {
+ value = input;
+ setValid(true);
+ } else {
+ throw new IllegalArgumentException("Incompatible value type description'" + inpvalueTypeDescr
+ + "' passed, expected '" + valueTypeDescr + "'.");
+ }
+ }
+
+ /**
+ * Returns a deep copy of given {@code Object}, so modifications in one do not
+ * affect to other.
+ *
+ * @param value
+ * The object which will be copied.
+ * @param valueClass
+ * The class of the value object.
+ * @return The copy is returned.
+ */
+ private static Object createDeepCopy(Object value, Class<?> valueClass) {
+ int length = Array.getLength(value);
+
+ if (valueClass.getComponentType().isPrimitive()) {
+ Object copy = Array.newInstance(valueClass.getComponentType(), length);
+ System.arraycopy(value, 0, copy, 0, length);
+ return copy;
+ } else {
+ if (value instanceof byte[][]) {
+ return Arrays.stream((byte[][]) value).map(v -> v.clone()).toArray(byte[][]::new);
+ } else if (value instanceof FileLink[]) {
+ return Arrays.stream((FileLink[]) value).map(FileLink::new).toArray(FileLink[]::new);
+ } else {
+ return Arrays.copyOf((Object[]) value, length);
+ }
+ }
+ }
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/ValueType.java b/src/main/java/org/eclipse/mdm/api/base/model/ValueType.java
index e4f9a6a..3639675 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/ValueType.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/ValueType.java
@@ -18,7 +18,7 @@
* @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
* @author Sebastian Dirsch, Gigatronik Ingolstadt GmbH
*/
-public class ValueType<T> extends EnumerationValue {
+public final class ValueType<T> extends EnumerationValue {
// ======================================================================
// Enumerations
@@ -28,145 +28,148 @@
* A {@link Value} with this type contains a {@code String} value and
* replaces {@code null} with an empty {@code String}.
*/
- public static final ValueType<String> STRING = new ValueType<String>(String.class, "");
+ public static final ValueType<String> STRING = new ValueType<>(0, String.class, "");
/**
* A {@link Value} with this type contains a {@code String[]} value replaces
* {@code null} with an empty {@code String} array.
*/
- public static final ValueType<String[]> STRING_SEQUENCE = new ValueType<String[]>(String[].class, new String[0]);
+ public static final ValueType<String[]> STRING_SEQUENCE = new ValueType<>(1, String[].class, new String[0]);
/**
* A {@link Value} with this type contains a {@link LocalDateTime} value and
* does not replace {@code null}.
*/
- public static final ValueType<LocalDateTime> DATE = new ValueType<LocalDateTime>(LocalDateTime.class, null);
+ public static final ValueType<LocalDateTime> DATE = new ValueType<>(2, LocalDateTime.class, null);
/**
* A {@link Value} with this type contains a {@code LocalDateTime[]} value
* and replaces {@code null} with an empty {@code LocalDateTime} array.
*/
- public static final ValueType<LocalDateTime[]> DATE_SEQUENCE = new ValueType<LocalDateTime[]>(LocalDateTime[].class, new LocalDateTime[0]);
+ public static final ValueType<LocalDateTime[]> DATE_SEQUENCE = new ValueType<>(3, LocalDateTime[].class,
+ new LocalDateTime[0]);
/**
* A {@link Value} with this type contains a {@link Boolean} value and
* replaces {@code null} with {@link Boolean#FALSE}.
*/
- public static final ValueType<Boolean> BOOLEAN = new ValueType<Boolean>(Boolean.class, Boolean.FALSE);
+ public static final ValueType<Boolean> BOOLEAN = new ValueType<>(4, Boolean.class, Boolean.FALSE);
/**
* A {@link Value} with this type contains a {@code boolean[]} value and
* replaces {@code null} with an empty {@code boolean} array.
*/
- public static final ValueType<boolean[]> BOOLEAN_SEQUENCE = new ValueType<boolean[]>(boolean[].class, new boolean[0]);
+ public static final ValueType<boolean[]> BOOLEAN_SEQUENCE = new ValueType<>(5, boolean[].class, new boolean[0]);
/**
* A {@link Value} with this type contains a {@link Byte} value and replaces
* {@code null} with a {@code Byte} containing zero.
*/
- public static final ValueType<Byte> BYTE = new ValueType<Byte>(Byte.class, Byte.valueOf((byte) 0));
+ public static final ValueType<Byte> BYTE = new ValueType<>(6, Byte.class, Byte.valueOf((byte) 0));
/**
* A {@link Value} with this type contains a {@code byte[]} value and
* replaces {@code null} with an empty {@code byte} array.
*/
- public static final ValueType<byte[]> BYTE_SEQUENCE = new ValueType<byte[]>(byte[].class, new byte[0]);
+ public static final ValueType<byte[]> BYTE_SEQUENCE = new ValueType<>(7, byte[].class, new byte[0]);
/**
* A {@link Value} with this type contains a {@link Short} value and
* replaces {@code null} with a {@code Short} containing zero.
*/
- public static final ValueType<Short> SHORT = new ValueType<Short>(Short.class, Short.valueOf((short) 0));
+ public static final ValueType<Short> SHORT = new ValueType<>(8, Short.class, Short.valueOf((short) 0));
/**
* A {@link Value} with this type contains a {@code short[]} value and
* replaces {@code null} with an empty {@code short} array.
*/
- public static final ValueType<short[]> SHORT_SEQUENCE = new ValueType<short[]>(short[].class, new short[0]);
+ public static final ValueType<short[]> SHORT_SEQUENCE = new ValueType<>(9, short[].class, new short[0]);
/**
* A {@link Value} with this type contains a {@link Integer} value and
* replaces {@code null} with a {@code Integer} containing zero.
*/
- public static final ValueType<Integer> INTEGER = new ValueType<Integer>(Integer.class, Integer.valueOf(0));
+ public static final ValueType<Integer> INTEGER = new ValueType<>(10, Integer.class, Integer.valueOf(0));
/**
* A {@link Value} with this type contains a {@code int[]} value and
* replaces {@code null} with an empty {@code int} array.
*/
- public static final ValueType<int[]> INTEGER_SEQUENCE = new ValueType<int[]>(int[].class, new int[0]);
+ public static final ValueType<int[]> INTEGER_SEQUENCE = new ValueType<>(11, int[].class, new int[0]);
/**
* A {@link Value} with this type contains a {@link Long} value and replaces
* {@code null} with a {@code Long} containing zero.
*/
- public static final ValueType<Long> LONG = new ValueType<Long>(Long.class, Long.valueOf(0));
+ public static final ValueType<Long> LONG = new ValueType<>(12, Long.class, Long.valueOf(0));
/**
* A {@link Value} with this type contains a {@code long[]} value and
* replaces {@code null} with an empty {@code long} array.
*/
- public static final ValueType<long[]> LONG_SEQUENCE = new ValueType<long[]>(long[].class, new long[0]);
+ public static final ValueType<long[]> LONG_SEQUENCE = new ValueType<>(13, long[].class, new long[0]);
/**
* A {@link Value} with this type contains a {@link Float} value and
* replaces {@code null} with a {@code Float} containing zero.
*/
- public static final ValueType<Float> FLOAT = new ValueType<Float>(Float.class, Float.valueOf(0));
+ public static final ValueType<Float> FLOAT = new ValueType<>(14, Float.class, Float.valueOf(0));
/**
* A {@link Value} with this type contains a {@code float[]} value and
* replaces {@code null} with an empty {@code float} array.
*/
- public static final ValueType<float[]> FLOAT_SEQUENCE = new ValueType<float[]>(float[].class, new float[0]);
+ public static final ValueType<float[]> FLOAT_SEQUENCE = new ValueType<>(15, float[].class, new float[0]);
/**
* A {@link Value} with this type contains a {@link Double} value and
* replaces {@code null} with a {@code Double} containing zero.
*/
- public static final ValueType<Double> DOUBLE = new ValueType<Double>(Double.class, Double.valueOf(0));
+ public static final ValueType<Double> DOUBLE = new ValueType<>(16, Double.class, Double.valueOf(0));
/**
* A {@link Value} with this type contains a {@code double[]} value and
* replaces {@code null} with an empty {@code double} array.
*/
- public static final ValueType<double[]> DOUBLE_SEQUENCE = new ValueType<double[]>(double[].class, new double[0]);
+ public static final ValueType<double[]> DOUBLE_SEQUENCE = new ValueType<>(17, double[].class, new double[0]);
/**
* A {@link Value} with this type contains a {@code byte[]} value and
* replaces {@code null} with an empty {@code byte} array.
*/
- public static final ValueType<byte[]> BYTE_STREAM = new ValueType<byte[]>(byte[].class, new byte[0]);
+ public static final ValueType<byte[]> BYTE_STREAM = new ValueType<>(18, byte[].class, new byte[0]);
/**
* A {@link Value} with this type contains a {@code byte[][]} value and
* replaces {@code null} with an empty {@code byte[][]} array.
*/
- public static final ValueType<byte[][]> BYTE_STREAM_SEQUENCE = new ValueType<byte[][]>(byte[][].class, new byte[0][]);
+ public static final ValueType<byte[][]> BYTE_STREAM_SEQUENCE = new ValueType<>(19, byte[][].class, new byte[0][]);
/**
* A {@link Value} with this type contains a {@link FloatComplex} value and
* does not replaces {@code null}.
*/
- public static final ValueType<FloatComplex> FLOAT_COMPLEX = new ValueType<FloatComplex>(FloatComplex.class, null);
+ public static final ValueType<FloatComplex> FLOAT_COMPLEX = new ValueType<>(22, FloatComplex.class, null);
/**
* A {@link Value} with this type contains a {@code FloatComplex[]} value
* and replaces {@code null} with an empty {@code FloatComplex[]} array.
*/
- public static final ValueType<FloatComplex[]> FLOAT_COMPLEX_SEQUENCE = new ValueType<FloatComplex[]>(FloatComplex[].class, new FloatComplex[0]);
+ public static final ValueType<FloatComplex[]> FLOAT_COMPLEX_SEQUENCE = new ValueType<>(21, FloatComplex[].class,
+ new FloatComplex[0]);
/**
* A {@link Value} with this type contains a {@link DoubleComplex} value and
* does not replaces {@code null}.
*/
- public static final ValueType<DoubleComplex> DOUBLE_COMPLEX = new ValueType<DoubleComplex>(DoubleComplex.class, null);
+ public static final ValueType<DoubleComplex> DOUBLE_COMPLEX = new ValueType<>(22, DoubleComplex.class, null);
/**
* A {@link Value} with this type contains a {@code DoubleComplex[]} value
* and replaces {@code null} with an empty {@code DoubleComplex[]} array.
*/
- public static final ValueType<DoubleComplex[]> DOUBLE_COMPLEX_SEQUENCE = new ValueType<DoubleComplex[]>(DoubleComplex[].class, new DoubleComplex[0]);
+ public static final ValueType<DoubleComplex[]> DOUBLE_COMPLEX_SEQUENCE = new ValueType<>(23, DoubleComplex[].class,
+ new DoubleComplex[0]);
/**
* A {@link Value} with this type contains a modeled enumeration constant
@@ -175,7 +178,7 @@
* @see #create(Class, String)
* @see #create(Class, String, String, boolean, Object)
*/
- public static final ValueType<EnumerationValue> ENUMERATION = new ValueType<EnumerationValue>();
+ public static final ValueType<EnumerationValue> ENUMERATION = new ValueType<>(24);
/**
* A {@link Value} with this type contains a modeled enumeration constant
@@ -185,31 +188,32 @@
* @see #create(Class, String)
* @see #create(Class, String, String, boolean, Object)
*/
- public static final ValueType<EnumerationValue[]> ENUMERATION_SEQUENCE = new ValueType<EnumerationValue[]>();
+ public static final ValueType<EnumerationValue[]> ENUMERATION_SEQUENCE = new ValueType<>(25);
/**
* A {@link Value} with this type contains a {@link FileLink} value and does
* not replace {@code null}.
*/
- public static final ValueType<FileLink> FILE_LINK = new ValueType<FileLink>(FileLink.class, null);
+ public static final ValueType<FileLink> FILE_LINK = new ValueType<>(26, FileLink.class, null);
/**
* A {@link Value} with this type contains a {@code FileLink[]} value and
* replaces {@code null} with an empty {@code FileLink} array.
*/
- public static final ValueType<FileLink[]> FILE_LINK_SEQUENCE = new ValueType<FileLink[]>(FileLink[].class, new FileLink[0]);
+ public static final ValueType<FileLink[]> FILE_LINK_SEQUENCE = new ValueType<>(27, FileLink[].class,
+ new FileLink[0]);
/**
* TODO ...
*/
- public static final ValueType<Object> BLOB = new ValueType<Object>(Object.class, null);
+ public static final ValueType<Object> BLOB = new ValueType<>(28, Object.class, null);
/**
* A {@link Value} with this type contains a {@link Object} value and does
* not replace {@code null}. This value type does not have a corresponding
* sequence type.
*/
- public static final ValueType<Void> UNKNOWN = new ValueType<Void>();
+ public static final ValueType<Void> UNKNOWN = new ValueType<>(29);
// ======================================================================
// Instance variables
@@ -227,16 +231,12 @@
*/
private final T defaultValue;
- // ======================================================================
- // Constructors
- // ======================================================================
-
/**
* Constructor - May only be used to create {@link #ENUMERATION},
* {@link #ENUMERATION_SEQUENCE} or {@link #UNKNOWN} types.
*/
- private ValueType() {
- this(null, null);
+ private ValueType(int ord) {
+ this(ord, null, null);
}
/**
@@ -249,7 +249,7 @@
* Will be used as {@code null} replacement in
* {@link Value#set(Object)}.
*/
- private ValueType(Class<T> type, T defaultValue) {
+ private ValueType(int ord, Class<T> type, T defaultValue) {
this.type = type;
this.defaultValue = defaultValue;
}
@@ -374,7 +374,8 @@
* @throws IllegalStateException
* Thrown if {@link #isEnumerationType()} returns {@code false}.
*/
- public <E extends EnumerationValue> Value create(String name, String unit, boolean valid, Object input, String valueTypeDescr) {
+ public <E extends EnumerationValue> Value create(String name, String unit, boolean valid, Object input,
+ String valueTypeDescr) {
if (isEnumerationType()) {
Object nullReplacement = null;
Class<?> valueClass = EnumerationValue.class;
@@ -991,9 +992,8 @@
* Returns the sequence version of this value type. This method returns
* itself, if this value type is a sequence type.
*
- * If you extend the class ValueType, you have to ensure that T contains a field
- * of the correct name and type,
- * otherwise a runtime error will occur.
+ * If you extend the class ValueType, you have to ensure that T contains a
+ * field of the correct name and type, otherwise a runtime error will occur.
*
* @return The sequence version of this value type is returned.
*/
@@ -1010,9 +1010,8 @@
* Returns the scalar version of this value type. This method returns
* itself, if this value type is a scalar type.
*
- * If you extend the class ValueType, you have to ensure that T
- * contains a field of the correct name and type,
- * otherwise a runtime error will occur.
+ * If you extend the class ValueType, you have to ensure that T contains a
+ * field of the correct name and type, otherwise a runtime error will occur.
*
* @return The sequence version of this value type is returned.
*/
@@ -1039,5 +1038,4 @@
return type;
}
-
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/model/VersionState.java b/src/main/java/org/eclipse/mdm/api/base/model/VersionState.java
index 9d242ab..6416f4d 100644
--- a/src/main/java/org/eclipse/mdm/api/base/model/VersionState.java
+++ b/src/main/java/org/eclipse/mdm/api/base/model/VersionState.java
@@ -26,7 +26,7 @@
* An entity with this version state is still editable and hence not allowed
* be used when creating new entities.
*/
- public static final VersionState EDITABLE = new VersionState();
+ public static final VersionState EDITABLE = new VersionState(0);
/**
* An entity with this version state is no longer editable and is allowed to
@@ -36,7 +36,7 @@
* <b>Note:</b> If an entity's version state is this state, then its version
* state is only allowed to be changed to {@link #ARCHIVED}.
*/
- public static final VersionState VALID = new VersionState();
+ public static final VersionState VALID = new VersionState(1);
/**
* An entity with this version state is neither editable nor is it allowed
@@ -46,7 +46,7 @@
* <b>Note:</b> If an entity's version state is this state, then its version
* state is no longer allowed to be changed.
*/
- public static final VersionState ARCHIVED = new VersionState();
+ public static final VersionState ARCHIVED = new VersionState(2);
// ======================================================================
// Public methods
@@ -81,5 +81,11 @@
public boolean isArchived() {
return ARCHIVED == this;
}
-
+
+ /**
+ * Constructor, ensures the correct order
+ */
+ VersionState(int ord) {
+ super(ord);
+ }
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/notification/NotificationFilter.java b/src/main/java/org/eclipse/mdm/api/base/notification/NotificationFilter.java
index d3409e0..2adbc3e 100644
--- a/src/main/java/org/eclipse/mdm/api/base/notification/NotificationFilter.java
+++ b/src/main/java/org/eclipse/mdm/api/base/notification/NotificationFilter.java
@@ -5,7 +5,7 @@
import java.util.HashSet;
import java.util.Set;
-import org.eclipse.mdm.api.base.query.EntityType;
+import org.eclipse.mdm.api.base.adapter.EntityType;
/**
* Class represents a filter for notifications.
diff --git a/src/main/java/org/eclipse/mdm/api/base/notification/NotificationListener.java b/src/main/java/org/eclipse/mdm/api/base/notification/NotificationListener.java
index 63344d9..0ac0ca8 100644
--- a/src/main/java/org/eclipse/mdm/api/base/notification/NotificationListener.java
+++ b/src/main/java/org/eclipse/mdm/api/base/notification/NotificationListener.java
@@ -2,9 +2,9 @@
import java.util.List;
+import org.eclipse.mdm.api.base.adapter.EntityType;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.User;
-import org.eclipse.mdm.api.base.query.EntityType;
/**
* Listener interface for notifications.
diff --git a/src/main/java/org/eclipse/mdm/api/base/notification/NotificationManager.java b/src/main/java/org/eclipse/mdm/api/base/notification/NotificationService.java
similarity index 97%
rename from src/main/java/org/eclipse/mdm/api/base/notification/NotificationManager.java
rename to src/main/java/org/eclipse/mdm/api/base/notification/NotificationService.java
index f3a0243..6093473 100644
--- a/src/main/java/org/eclipse/mdm/api/base/notification/NotificationManager.java
+++ b/src/main/java/org/eclipse/mdm/api/base/notification/NotificationService.java
@@ -6,7 +6,7 @@
* @since 1.0.0
* @author Matthias Koller, Peak Solution GmbH
*/
-public interface NotificationManager {
+public interface NotificationService {
/**
* Registers a NotificationListener at the underlying notification service.
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/BracketOperator.java b/src/main/java/org/eclipse/mdm/api/base/query/BracketOperator.java
index 4916d6a..355d0bc 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/BracketOperator.java
+++ b/src/main/java/org/eclipse/mdm/api/base/query/BracketOperator.java
@@ -25,5 +25,21 @@
/**
* Right parenthesis.
*/
- CLOSE
+ CLOSE;
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Enum#toString()
+ */
+ @Override
+ public String toString() {
+ switch (this) {
+ case OPEN:
+ return "(";
+ case CLOSE:
+ return ")";
+ default:
+ return this.toString();
+ }
+ }
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/ComparisonOperator.java b/src/main/java/org/eclipse/mdm/api/base/query/ComparisonOperator.java
index a40211c..aa3c530 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/ComparisonOperator.java
+++ b/src/main/java/org/eclipse/mdm/api/base/query/ComparisonOperator.java
@@ -10,6 +10,7 @@
import java.util.Arrays;
+import org.eclipse.mdm.api.base.adapter.Attribute;
import org.eclipse.mdm.api.base.model.ValueType;
/**
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/Condition.java b/src/main/java/org/eclipse/mdm/api/base/query/Condition.java
index b73d093..eda235a 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/Condition.java
+++ b/src/main/java/org/eclipse/mdm/api/base/query/Condition.java
@@ -8,6 +8,9 @@
package org.eclipse.mdm.api.base.query;
+import java.util.Objects;
+
+import org.eclipse.mdm.api.base.adapter.Attribute;
import org.eclipse.mdm.api.base.model.Value;
/**
@@ -82,5 +85,42 @@
public ComparisonOperator getComparisonOperator() {
return comparisonOperator;
}
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof Condition)) {
+ return false;
+ }
+ Condition condition = (Condition) other;
+
+ return Objects.equals(this.attribute, condition.attribute)
+ && Objects.equals(this.value, condition.value)
+ && Objects.equals(this.comparisonOperator, condition.comparisonOperator);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(attribute, value, comparisonOperator);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return attribute.getEntityType().getName() + "." + attribute.getName() + " " + comparisonOperator + " " + value;
+ }
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/DataAccessException.java b/src/main/java/org/eclipse/mdm/api/base/query/DataAccessException.java
index c291aab..2f8cbe0 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/DataAccessException.java
+++ b/src/main/java/org/eclipse/mdm/api/base/query/DataAccessException.java
@@ -14,7 +14,7 @@
* @since 1.0.0
* @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
*/
-public final class DataAccessException extends Exception {
+public final class DataAccessException extends RuntimeException {
// ======================================================================
// Class variables
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/Filter.java b/src/main/java/org/eclipse/mdm/api/base/query/Filter.java
index 3be3904..4b70368 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/Filter.java
+++ b/src/main/java/org/eclipse/mdm/api/base/query/Filter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016 Gigatronik Ingolstadt GmbH
+ * Copyright (c) 2016 Gigatronik Ingolstadt GmbH and others
* 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
@@ -14,8 +14,15 @@
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.search.SearchQuery;
+import org.eclipse.mdm.api.base.search.SearchService;
+
/**
* A filter is a sequence of {@link FilterItem}s containing {@link BooleanOperator}s or
* {@link Condition}s.
@@ -352,7 +359,7 @@
* @return Returns this filter.
*/
public Filter merge(Filter filter) {
- boolean addBrackets = !filter.isInverted() || filter.hasMultiple() && !(operatorItem == filter.operatorItem);
+ boolean addBrackets = filter.hasMultiple() && operatorItem != filter.operatorItem && !filter.isInverted();
insertOperator();
if (addBrackets) {
@@ -487,4 +494,43 @@
return filterItems.size() > 1;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof Filter)) {
+ return false;
+ }
+
+ Filter filter = (Filter) other;
+
+ // Deque does not implement equals
+ return Arrays.equals(this.filterItems.toArray(new FilterItem[0]), filter.filterItems.toArray(new FilterItem[0]))
+ && Objects.equals(this.operatorItem, filter.operatorItem);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(filterItems, operatorItem);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return this.stream().map(i -> Objects.toString(i)).collect(Collectors.joining(""));
+ }
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/FilterItem.java b/src/main/java/org/eclipse/mdm/api/base/query/FilterItem.java
index 89c8f0f..c2e57c9 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/FilterItem.java
+++ b/src/main/java/org/eclipse/mdm/api/base/query/FilterItem.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016 Gigatronik Ingolstadt GmbH
+ * Copyright (c) 2016 Gigatronik Ingolstadt GmbH and others
* 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
@@ -8,6 +8,8 @@
package org.eclipse.mdm.api.base.query;
+import java.util.Objects;
+
/**
* Filter item contains either a {@link Condition} or an {@link BooleanOperator}.
*
@@ -170,5 +172,49 @@
throw new IllegalStateException("Item does not contain a condition.");
}
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof FilterItem)) {
+ return false;
+ }
+
+ FilterItem filterItem = (FilterItem) other;
+
+ return Objects.equals(this.condition, filterItem.condition)
+ && Objects.equals(this.booleanOperator, filterItem.booleanOperator)
+ && Objects.equals(this.bracketOperator, filterItem.bracketOperator);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(condition, booleanOperator, bracketOperator);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ if (isBooleanOperator()) {
+ return " " + booleanOperator.toString() + " ";
+ } else if (isBracketOperator()) {
+ return bracketOperator.toString();
+ } else {
+ return condition.toString();
+ }
+ }
}
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/Query.java b/src/main/java/org/eclipse/mdm/api/base/query/Query.java
index ae4be98..9d6b277 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/Query.java
+++ b/src/main/java/org/eclipse/mdm/api/base/query/Query.java
@@ -12,6 +12,10 @@
import java.util.List;
import java.util.Optional;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+
/**
* Provides methods to easily build queries by adding select, join, group by and
* order by statements. Finally an optional {@link Filter} may be given to
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/QueryService.java b/src/main/java/org/eclipse/mdm/api/base/query/QueryService.java
new file mode 100644
index 0000000..389b68d
--- /dev/null
+++ b/src/main/java/org/eclipse/mdm/api/base/query/QueryService.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017 Peak Solution GmbH
+ * 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
+ */
+package org.eclipse.mdm.api.base.query;
+
+/**
+ * The {@link QueryService} provides access to the low level query API.
+ *
+ * A {@link Query}, created by this service, can be used to build and execute
+ * queries on the underlying datastore. The results are returned as a list
+ * of {@link Result}s.
+ *
+ * @since 1.0.0
+ */
+public interface QueryService {
+
+ /**
+ * Creates a new and empty {@link Query}.
+ *
+ * @return Created {@code Query} is returned.
+ */
+ Query createQuery();
+}
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/Record.java b/src/main/java/org/eclipse/mdm/api/base/query/Record.java
index 53778ab..979932a 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/Record.java
+++ b/src/main/java/org/eclipse/mdm/api/base/query/Record.java
@@ -12,6 +12,9 @@
import java.util.Map;
import java.util.Optional;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
import org.eclipse.mdm.api.base.model.Value;
/**
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/Result.java b/src/main/java/org/eclipse/mdm/api/base/query/Result.java
index bf11b7a..472d31b 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/Result.java
+++ b/src/main/java/org/eclipse/mdm/api/base/query/Result.java
@@ -14,10 +14,12 @@
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
import org.eclipse.mdm.api.base.model.Value;
/**
- * A result consists of one or more {@link Record}s.
+ * A result consists of one or more {@link Record}s, which is mapped from an {@link EntityType}
*
* @since 1.0.0
* @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
@@ -25,16 +27,8 @@
*/
public final class Result implements Iterable<Record> {
- // ======================================================================
- // Instance variables
- // ======================================================================
-
private final Map<EntityType, Record> records = new HashMap<>();
- // ======================================================================
- // Public methods
- // ======================================================================
-
/**
* Adds given {@link Record} to this result.
*
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/SearchQuery.java b/src/main/java/org/eclipse/mdm/api/base/search/SearchQuery.java
similarity index 95%
rename from src/main/java/org/eclipse/mdm/api/base/query/SearchQuery.java
rename to src/main/java/org/eclipse/mdm/api/base/search/SearchQuery.java
index e4f266c..1652e06 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/SearchQuery.java
+++ b/src/main/java/org/eclipse/mdm/api/base/search/SearchQuery.java
@@ -6,11 +6,16 @@
* http://www.eclipse.org/legal/epl-v10.html
*/
-package org.eclipse.mdm.api.base.query;
+package org.eclipse.mdm.api.base.search;
import java.util.List;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.Result;
/**
* This is an interface for predefined search query implementations.
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/SearchService.java b/src/main/java/org/eclipse/mdm/api/base/search/SearchService.java
similarity index 84%
rename from src/main/java/org/eclipse/mdm/api/base/query/SearchService.java
rename to src/main/java/org/eclipse/mdm/api/base/search/SearchService.java
index e6c3b8a..763dbb4 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/SearchService.java
+++ b/src/main/java/org/eclipse/mdm/api/base/search/SearchService.java
@@ -6,19 +6,25 @@
* http://www.eclipse.org/legal/epl-v10.html
*/
-package org.eclipse.mdm.api.base.query;
+package org.eclipse.mdm.api.base.search;
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.Record;
+import org.eclipse.mdm.api.base.query.Result;
/**
* This search service uses given {@link Entity} type to execute the associated
- * {@link SearchQuery}.
+ * predefined {@link SearchQuery} and returns the results.
*
* @since 1.0.0
* @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
@@ -32,10 +38,6 @@
*/
public interface SearchService {
- // ======================================================================
- // Public methods
- // ======================================================================
-
/**
* Returns all {@link Entity} types this search service provides a
* predefined {@link SearchQuery} for.
@@ -135,6 +137,10 @@
* the {@code SearchQuery} associated with given {@link Entity} type. This
* method selects all {@link Attribute}s of each given {@code EntityType}.
*
+ * It is only guaranteed that this method loads the selected entities,
+ * and their relations among themselves. No information about additional related entities
+ * is necessarily loaded.
+ *
* <p>
* <b>Note:</b> Related {@code Record}s may be merged according to the
* cardinality of the associated {@link Relation}.
@@ -146,8 +152,7 @@
* @param entityTypes
* Select statements will be added for all {@code Attribute}s of
* each given {@code EntityType}.
- * @return All {@link Result}s are returned in a {@code Map}, which maps
- * entities to related {@link Record}s.
+ * @return All matched entities are returned in a {@code List}.
* @throws DataAccessException
* Thrown in case of errors while executing the
* {@code SearchQuery} or analyzing its {@code Result}s.
@@ -160,7 +165,7 @@
* @see #fetch(Class, List)
* @see Record#merge(Record)
*/
- default <T extends Entity> Map<T, Result> fetchComplete(Class<T> entityCass, List<EntityType> entityTypes)
+ default <T extends Entity> List<T> fetchComplete(Class<T> entityCass, List<EntityType> entityTypes)
throws DataAccessException {
return fetchComplete(entityCass, entityTypes, Filter.and());
}
@@ -170,6 +175,10 @@
* {@link EntityType}s and {@link Filter}. Both must be fully supported by
* the {@code SearchQuery} associated with given {@link Entity} type. This
* method selects all {@link Attribute}s of each given {@code EntityType}.
+ *
+ * It is only guaranteed that this method loads the selected entities,
+ * and their relations among themselves. No information about additional related entities
+ * is necessarily loaded.
*
* <p>
* <b>Note:</b> Related {@code Record}s may be merged according to the
@@ -184,8 +193,7 @@
* each given {@code EntityType}.
* @param filter
* The criteria sequence.
- * @return All {@link Result}s are returned in a {@code Map}, which maps
- * entities to related {@link Record}s.
+ * @return All matched entities are returned in a {@code List}.
* @throws DataAccessException
* Thrown in case of errors while executing the
* {@code SearchQuery} or analyzing its {@code Result}s.
@@ -198,12 +206,15 @@
* @see #fetch(Class, List, Filter)
* @see Record#merge(Record)
*/
- <T extends Entity> Map<T, Result> fetchComplete(Class<T> entityClass, List<EntityType> entityTypes, Filter filter)
+ <T extends Entity> List<T> fetchComplete(Class<T> entityClass, List<EntityType> entityTypes, Filter filter)
throws DataAccessException;
/**
* Executes the associated {@link SearchQuery} and returns all available
* instances of the specified {@link Entity} type.
+ *
+ * It is only guaranteed that this method loads the selected entity,
+ * no information about related entities is necessarily loaded.
*
* @param <T>
* Type of the entities that will be generated for each result.
@@ -227,6 +238,9 @@
* Executes the associated {@link SearchQuery} with given {@link Filter}.
* The {@code Filter} must be fully supported by the {@code SearchQuery}
* associated with given {@link Entity} type.
+ * It is only guaranteed that this method loads the selected entity,
+ * no information about related entities is necessarily loaded.
+ *
*
* @param <T>
* Type of the entities that will be generated for each result.
@@ -247,7 +261,7 @@
* @see #fetch(Class)
*/
default <T extends Entity> List<T> fetch(Class<T> entityClass, Filter filter) throws DataAccessException {
- return fetch(entityClass, Collections.emptyList(), filter).keySet().stream().collect(Collectors.toList());
+ return fetch(entityClass, Collections.emptyList(), filter);
}
/**
@@ -255,6 +269,9 @@
* {@link Attribute}s. The {@code Attribute}s must be fully supported by the
* {@code SearchQuery} associated with given {@link Entity} type. This
* method allows fine grained {@link Record} configuration.
+ *
+ * It is only guaranteed that this method loads the selected entity or attributes,
+ * no additional information about related entities is necessarily loaded.
*
* <p>
* <b>Note:</b> Related {@code Record}s may be merged according to the
@@ -267,8 +284,7 @@
* @param attributes
* Select statements will be added for each {@code
* Attribute}.
- * @return All {@link Result}s are returned in a {@code Map}, which maps
- * entities to related {@code Record}s.
+ * @return All matched entities are returned in a {@code List}.
* @throws DataAccessException
* Thrown in case of errors while executing the
* {@code SearchQuery} or analyzing its {@code Result}s.
@@ -281,7 +297,7 @@
* @see #fetchComplete(Class, List)
* @see Record#merge(Record)
*/
- default <T extends Entity> Map<T, Result> fetch(Class<T> entityClass, List<Attribute> attributes)
+ default <T extends Entity> List<T> fetch(Class<T> entityClass, List<Attribute> attributes)
throws DataAccessException {
return fetch(entityClass, attributes, Filter.and());
}
@@ -291,6 +307,9 @@
* and {@link Filter}. Both must be fully supported by the
* {@code SearchQuery} associated with given {@link Entity} type. This
* method allows fine grained {@link Record} configuration.
+ *
+ * It is only guaranteed that this method loads the selected entity or attributes,
+ * no additional information about related entities is necessarily loaded.
*
* <p>
* <b>Note:</b> Related {@code Record}s may be merged according to the
@@ -305,8 +324,7 @@
* Attribute}.
* @param filter
* The criteria sequence.
- * @return All {@link Result}s are returned in a {@code Map}, which maps
- * entities to related {@code Record}s.
+ * @return All matched entities are returned in a {@code List}.
* @throws DataAccessException
* Thrown in case of errors while executing the
* {@code SearchQuery} or analyzing its {@code Result}s.
@@ -319,7 +337,7 @@
* @see #fetchComplete(Class, List, Filter)
* @see Record#merge(Record)
*/
- <T extends Entity> Map<T, Result> fetch(Class<T> entityClass, List<Attribute> attributes, Filter filter)
+ <T extends Entity> List<T> fetch(Class<T> entityClass, List<Attribute> attributes, Filter filter)
throws DataAccessException;
/**
@@ -327,7 +345,10 @@
* and {@link Filter}. Both must be fully supported by the
* {@code SearchQuery} associated with given {@link Entity} type. This
* method allows fine grained {@link Record} configuration. This method
- * allows to specify a fulltext search query.
+ * allows to specify a fulltext search query string.
+ *
+ * It is only guaranteed that this method loads the selected entity or attributes,
+ * no additional information about related entities is necessarily loaded.
*
* <p>
* <b>Note:</b> Related {@code Record}s may be merged according to the
diff --git a/src/main/java/org/eclipse/mdm/api/base/query/Searchable.java b/src/main/java/org/eclipse/mdm/api/base/search/Searchable.java
similarity index 93%
rename from src/main/java/org/eclipse/mdm/api/base/query/Searchable.java
rename to src/main/java/org/eclipse/mdm/api/base/search/Searchable.java
index cab0bee..355bcda 100644
--- a/src/main/java/org/eclipse/mdm/api/base/query/Searchable.java
+++ b/src/main/java/org/eclipse/mdm/api/base/search/Searchable.java
@@ -6,10 +6,12 @@
* http://www.eclipse.org/legal/epl-v10.html
*/
-package org.eclipse.mdm.api.base.query;
+package org.eclipse.mdm.api.base.search;
import java.util.List;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+
/**
* A searchable is used to describe the hierarchical order of
* {@link EntityType}s being used for searching.
diff --git a/src/test/java/org/eclipse/mdm/api/base/AttributeImpl.java b/src/test/java/org/eclipse/mdm/api/base/AttributeImpl.java
index 05d3253..7ab8187 100755
--- a/src/test/java/org/eclipse/mdm/api/base/AttributeImpl.java
+++ b/src/test/java/org/eclipse/mdm/api/base/AttributeImpl.java
@@ -8,10 +8,10 @@
package org.eclipse.mdm.api.base;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
import org.eclipse.mdm.api.base.model.Enumeration;
import org.eclipse.mdm.api.base.model.ValueType;
-import org.eclipse.mdm.api.base.query.Attribute;
-import org.eclipse.mdm.api.base.query.EntityType;
public class AttributeImpl implements Attribute {
diff --git a/src/test/java/org/eclipse/mdm/api/base/CoreImpl.java b/src/test/java/org/eclipse/mdm/api/base/CoreImpl.java
index 19bbb5c..46e7a14 100755
--- a/src/test/java/org/eclipse/mdm/api/base/CoreImpl.java
+++ b/src/test/java/org/eclipse/mdm/api/base/CoreImpl.java
@@ -11,7 +11,9 @@
import java.util.Collection;
import java.util.Map;
-import org.eclipse.mdm.api.base.model.Core;
+import org.eclipse.mdm.api.base.adapter.ChildrenStore;
+import org.eclipse.mdm.api.base.adapter.Core;
+import org.eclipse.mdm.api.base.adapter.EntityStore;
import org.eclipse.mdm.api.base.model.Value;
/**
diff --git a/src/test/java/org/eclipse/mdm/api/base/EntityFactoryImpl.java b/src/test/java/org/eclipse/mdm/api/base/EntityFactoryImpl.java
index 798dfaf..52703f1 100755
--- a/src/test/java/org/eclipse/mdm/api/base/EntityFactoryImpl.java
+++ b/src/test/java/org/eclipse/mdm/api/base/EntityFactoryImpl.java
@@ -10,9 +10,9 @@
import java.util.Optional;
+import org.eclipse.mdm.api.base.adapter.Core;
import org.eclipse.mdm.api.base.model.BaseEntityFactory;
import org.eclipse.mdm.api.base.model.ContextType;
-import org.eclipse.mdm.api.base.model.Core;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.User;
diff --git a/src/test/java/org/eclipse/mdm/api/base/EntityTypeImpl.java b/src/test/java/org/eclipse/mdm/api/base/EntityTypeImpl.java
index e723177..a8665a8 100755
--- a/src/test/java/org/eclipse/mdm/api/base/EntityTypeImpl.java
+++ b/src/test/java/org/eclipse/mdm/api/base/EntityTypeImpl.java
@@ -11,10 +11,10 @@
import java.util.List;
import org.eclipse.mdm.api.base.AttributeImpl.Type;
-import org.eclipse.mdm.api.base.query.Attribute;
-import org.eclipse.mdm.api.base.query.EntityType;
-import org.eclipse.mdm.api.base.query.Relation;
-import org.eclipse.mdm.api.base.query.RelationType;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.adapter.RelationType;
public class EntityTypeImpl implements EntityType {
diff --git a/src/test/java/org/eclipse/mdm/api/base/RelationImpl.java b/src/test/java/org/eclipse/mdm/api/base/RelationImpl.java
index 4ca2c79..0ca5eea 100755
--- a/src/test/java/org/eclipse/mdm/api/base/RelationImpl.java
+++ b/src/test/java/org/eclipse/mdm/api/base/RelationImpl.java
@@ -8,10 +8,10 @@
package org.eclipse.mdm.api.base;
-import org.eclipse.mdm.api.base.query.Attribute;
-import org.eclipse.mdm.api.base.query.EntityType;
-import org.eclipse.mdm.api.base.query.Relation;
-import org.eclipse.mdm.api.base.query.RelationType;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.adapter.RelationType;
public class RelationImpl implements Relation {
diff --git a/src/test/java/org/eclipse/mdm/api/base/model/ContextComponentTest.java b/src/test/java/org/eclipse/mdm/api/base/model/ContextComponentTest.java
new file mode 100644
index 0000000..8107d48
--- /dev/null
+++ b/src/test/java/org/eclipse/mdm/api/base/model/ContextComponentTest.java
@@ -0,0 +1,45 @@
+package org.eclipse.mdm.api.base.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.mdm.api.base.adapter.ChildrenStore;
+import org.eclipse.mdm.api.base.adapter.Core;
+import org.eclipse.mdm.api.base.adapter.EntityStore;
+
+public class ContextComponentTest {
+
+ @org.junit.Test
+ public void testGetContextRoot() {
+ BaseEntityFactory factory = spy(BaseEntityFactory.class);
+ Core rootCore = createCore("UNITUNDERTEST");
+ when(factory.createCore(ContextRoot.class, ContextType.UNITUNDERTEST)).thenReturn(rootCore);
+ Core componentCore = createCore("");
+ when(factory.createCore("Engine", ContextComponent.class)).thenReturn(componentCore);
+
+ ContextRoot contextRoot = factory.createContextRoot("Car", ContextType.UNITUNDERTEST);
+ ContextComponent contextComponent = factory.createContextComponent("Engine", contextRoot);
+
+ assertThat(contextComponent.getContextRoot()).isEqualTo(contextRoot);
+ }
+
+ private Core createCore(String type) {
+ Core core = mock(Core.class);
+
+ Map<String, Value> values = new HashMap<>();
+ values.put("Name", ValueType.STRING.create("Name"));
+ values.put("Version", ValueType.STRING.create("Version"));
+
+ when(core.getValues()).thenReturn(values);
+ when(core.getTypeName()).thenReturn(type);
+ when(core.getPermanentStore()).thenReturn(new EntityStore());
+ when(core.getChildrenStore()).thenReturn(new ChildrenStore());
+
+ return core;
+ }
+}
diff --git a/src/test/java/org/eclipse/mdm/api/base/model/ContextSensorTest.java b/src/test/java/org/eclipse/mdm/api/base/model/ContextSensorTest.java
new file mode 100644
index 0000000..0756434
--- /dev/null
+++ b/src/test/java/org/eclipse/mdm/api/base/model/ContextSensorTest.java
@@ -0,0 +1,49 @@
+package org.eclipse.mdm.api.base.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.mdm.api.base.adapter.ChildrenStore;
+import org.eclipse.mdm.api.base.adapter.Core;
+import org.eclipse.mdm.api.base.adapter.EntityStore;
+
+
+public class ContextSensorTest {
+
+ @org.junit.Test
+ public void testGetContextComponent() {
+ BaseEntityFactory factory = spy(BaseEntityFactory.class);
+ Core rootCore = createCore("TESTEQUIPMENT");
+ when(factory.createCore(ContextRoot.class, ContextType.TESTEQUIPMENT)).thenReturn(rootCore);
+ Core componentCore = createCore("");
+ when(factory.createCore("SensorDevice", ContextComponent.class)).thenReturn(componentCore);
+ Core sensorCore = createCore("");
+ when(factory.createCore("Sensor", ContextSensor.class)).thenReturn(sensorCore);
+
+ ContextRoot contextRoot = factory.createContextRoot("SensorDevices", ContextType.TESTEQUIPMENT);
+ ContextComponent contextComponent = factory.createContextComponent("SensorDevice", contextRoot);
+ ContextSensor contextSensor = factory.createContextSensor("Sensor", contextComponent);
+
+ assertThat(contextSensor.getContextComponent()).isEqualTo(contextComponent);
+ }
+
+ private Core createCore(String type) {
+ Core core = mock(Core.class);
+
+ Map<String, Value> values = new HashMap<>();
+ values.put("Name", ValueType.STRING.create("Name"));
+ values.put("Version", ValueType.STRING.create("Version"));
+
+ when(core.getValues()).thenReturn(values);
+ when(core.getTypeName()).thenReturn(type);
+ when(core.getPermanentStore()).thenReturn(new EntityStore());
+ when(core.getChildrenStore()).thenReturn(new ChildrenStore());
+
+ return core;
+ }
+}
diff --git a/src/test/java/org/eclipse/mdm/api/base/model/ModelTest.java b/src/test/java/org/eclipse/mdm/api/base/model/ModelTest.java
index f8e49a3..f214ca2 100755
--- a/src/test/java/org/eclipse/mdm/api/base/model/ModelTest.java
+++ b/src/test/java/org/eclipse/mdm/api/base/model/ModelTest.java
@@ -18,6 +18,7 @@
import org.eclipse.mdm.api.base.CoreImpl;
import org.eclipse.mdm.api.base.EntityFactoryImpl;
+import org.eclipse.mdm.api.base.adapter.Core;
import org.eclipse.mdm.api.base.massdata.UnitBuilder;
import org.eclipse.mdm.api.base.massdata.WriteRequest;
import org.eclipse.mdm.api.base.massdata.WriteRequestBuilder;