diff options
author | Matthias Koller | 2019-02-27 11:12:33 +0000 |
---|---|---|
committer | Matthias Koller | 2019-02-27 11:12:33 +0000 |
commit | a06539e576842b4d78baccfb38bcf26eaaaaf7a7 (patch) | |
tree | f673fd88b0f88302360a12623942e11a140ca98c | |
parent | e9e139185ea8df98b49d31af85a6efc08e751ce6 (diff) | |
parent | b5444eb1a875b04f8a71b93bfa6dd2b4a3fe40b5 (diff) | |
download | org.eclipse.mdm.api.odsadapter-a06539e576842b4d78baccfb38bcf26eaaaaf7a7.tar.gz org.eclipse.mdm.api.odsadapter-a06539e576842b4d78baccfb38bcf26eaaaaf7a7.tar.xz org.eclipse.mdm.api.odsadapter-a06539e576842b4d78baccfb38bcf26eaaaaf7a7.zip |
Merge branch 'dev'
Change-Id: Id94d3ca0c5488ea3cb220f871f7660d6a119fb40
17 files changed, 1104 insertions, 508 deletions
@@ -17,13 +17,13 @@ For more information regarding authorship of content, please consult the listed source code repository logs. Copyright (c) 2016-2018 Gigatronik Ingolstadt GmbH -Copyright (c) 2016-2018 Peak Solution GmbH +Copyright (c) 2016-2019 Peak Solution GmbH Copyright (c) 2017-2018 science + computing AG Tuebingen (ATOS SE) Copyright (c) 2017-2018 Canoo Engineering AG Copyright (c) 2017 Florian Schmitt -Copyright (c) 2017-2018 Angelika Wittek +Copyright (c) 2017-2019 Angelika Wittek Copyright (c) 2018 Elektronische Fahrwerksysteme GMBH -Copyright (c) 2018 Karakun AG +Copyright (c) 2018-2019 Karakun AG ## Declared Project Licenses @@ -61,7 +61,13 @@ commons-codec-1.2.jar (1.2) commons-httpclient-3.1.jar (3.1) * License: Apache License, 2.0 -commons-lang3-3.4.jar (3.4) +commons-lang3-3.8.1.jar (3.8.1) + * License: Apache License, 2.0 + +commons-text-1.6.jar (1.6) + * License: Apache License, 2.0 + +commons-math-2.2.jar (2.2) * License: Apache License, 2.0 gson-2.7.jar (2.7) @@ -71,7 +77,7 @@ Google Guava Version: 25.0-jre (25.0) * License: Apache License, 2.0 Gradle Wrapper (4.10.2) - * License: Apache License, 2.0 + * License: Apache License, 2.0 hk2-api-2.5.0-b05.jar (2.5.0-b05) * License: CDDL-1.1 @@ -130,6 +136,9 @@ jersey-media-jaxb-2.23.2.jar(2.23.2) jersey-media-sse-2.23.2.jar (2.23.2) * License: CDDL +jersey-media-multipart-2.23.2.jar (2.23.2) + * License: CDDL + jersey-server-2.23.2.jar (2.23.2) * License: Apache-2.0 @@ -317,10 +326,10 @@ Permission of use: From Dr. Ralph Noerenberg Date: 08/15/2016 "Herewith, we release the generated Client-Source-Code generated from our CORBA IDLs, namely -* CORBANotification Service (generated from „AvalonEvent.idl”) -* CORBAFileServer (generated from „CorbaFileServer.idl“), -Under the Eclipse Public License (EPL). This agreement does not include the „AvalonEvent.idl“ and -„CorbaFileServer.idl“ itself, which remain protected property of HighQSoft. " +* CORBANotification Service (generated from AvalonEvent.idl) +* CORBAFileServer (generated from CorbaFileServer.idl), +Under the Eclipse Public License (EPL). This agreement does not include the AvalonEvent.idl and +CorbaFileServer.idl itself, which remain protected property of HighQSoft. " OMG Notification Service Specification Version: 1.1 The terms of use are defined in section "Freely Available And Available diff --git a/build.gradle b/build.gradle index cb964a2..b4f00da 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,7 @@ description = 'MDM API - ODSAdapter' group = 'org.eclipse.mdm' -version = '5.1.0M1' +version = '5.1.0M2-SNAPSHOT' apply plugin: 'java' apply plugin: 'maven' @@ -94,7 +94,7 @@ dependencies { // querying es compile 'commons-httpclient:commons-httpclient:3.1' - compile 'org.apache.commons:commons-lang3:3.4' + compile 'org.apache.commons:commons-lang3:3.8.1' // testing testCompile 'junit:junit:4.12' @@ -140,7 +140,7 @@ task compileIDL(type: JavaExec) { main = 'com.sun.tools.corba.se.idl.toJavaPortable.Compile' // add 'fallTIE' if <Type>POA & <Type>POATie have to be generated - args '-td', 'src/gen/java/', 'src/main/idl/ods530.idl' + args '-fallTIE', '-td', 'src/gen/java/', 'src/main/idl/ods530.idl' outputs.dir("src/gen/java") } @@ -150,7 +150,7 @@ task compileNotificationServiceIDL(type: JavaExec) { main = 'com.sun.tools.corba.se.idl.toJavaPortable.Compile' - args '-emitAll', '-fall', '-i', 'src/main/idl/', '-td', 'src/gen/java/', 'src/main/idl/CosNotifyChannelAdmin.idl' + args '-emitAll', '-fallTIE', '-i', 'src/main/idl/', '-td', 'src/gen/java/', 'src/main/idl/CosNotifyChannelAdmin.idl' outputs.dir("src/gen/java") outputs.upToDateWhen { false } @@ -175,6 +175,15 @@ jar { metaInf { from 'LICENSE.txt' } } +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource +} + +artifacts { + archives sourcesJar +} + task deleteGenerated(type: Delete) { delete 'src/gen' delete 'build' diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContext.java b/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContext.java index 013c077..e1cb7fc 100644 --- a/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContext.java +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContext.java @@ -1,16 +1,16 @@ -/********************************************************************************
- * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information regarding copyright ownership.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- ********************************************************************************/
+/******************************************************************************** + * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ package org.eclipse.mdm.api.odsadapter; @@ -97,7 +97,7 @@ public class ODSContext implements ApplicationContext { @Override public Optional<EntityFactory> getEntityFactory() { try { - return Optional.of(new ODSEntityFactory(modelManager, entityManager.loadLoggedOnUser().get())); + return Optional.of(new ODSEntityFactory(modelManager, entityManager.loadLoggedOnUser())); } catch (DataAccessException e) { throw new IllegalStateException("Unable to load instance of the logged in user."); } diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContextFactory.java b/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContextFactory.java index 0546c46..4084697 100644 --- a/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContextFactory.java +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContextFactory.java @@ -1,16 +1,16 @@ -/********************************************************************************
- * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information regarding copyright ownership.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- ********************************************************************************/
+/******************************************************************************** + * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ package org.eclipse.mdm.api.odsadapter; @@ -62,7 +62,7 @@ public class ODSContextFactory implements ApplicationContextFactory { private static final Logger LOGGER = LoggerFactory.getLogger(ODSContextFactory.class); - private final ORB orb = ORB.init(new String[] {}, System.getProperties()); + private static final ORB orb = ORB.init(new String[] {}, System.getProperties()); public ODSContextFactory() { } diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java b/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java index bb7b141..bbbad94 100644 --- a/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java @@ -25,11 +25,13 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.asam.ods.AoException; import org.asam.ods.ApplicationStructure; import org.asam.ods.ElemId; import org.asam.ods.InstanceElement; +import org.asam.ods.T_LONGLONG; import org.eclipse.mdm.api.base.ServiceNotProvidedException; import org.eclipse.mdm.api.base.Transaction; import org.eclipse.mdm.api.base.adapter.EntityType; @@ -355,9 +357,25 @@ public class ODSEntityManager implements EntityManager { /** * {@inheritDoc} */ + public <T extends Entity> List<T> loadRelatedEntities(Entity entity, String relationName, Class<T> relatedClass) { + ODSEntityType entityType = ((ODSEntityType) context.getODSModelManager().getEntityType(entity)); + ElemId elemId = new ElemId(entityType.getODSID(), ODSConverter.toODSID(entity.getID())); + + try { + T_LONGLONG[] instanceIds = context.getAoSession().getApplElemAccess().getRelInst(elemId, relationName); + List<String> instanceIDs = Stream.of(instanceIds).map(ODSConverter::fromODSLong).map(l -> l.toString()).collect(Collectors.toList()); + return entityLoader.loadAll(new Key<>(relatedClass), instanceIDs); + } catch (AoException e) { + throw new DataAccessException("" + e.reason, e); // TODO + } + } + + /** + * {@inheritDoc} + */ @Override public List<MeasuredValues> readMeasuredValues(ReadRequest readRequest) throws DataAccessException { - return new ReadRequestHandler(odsModelManager).execute(readRequest); + return new ReadRequestHandler(odsModelManager, queryService).execute(readRequest); } /** diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/ReadRequestHandler.java b/src/main/java/org/eclipse/mdm/api/odsadapter/ReadRequestHandler.java index 7d4603e..44d32fd 100644 --- a/src/main/java/org/eclipse/mdm/api/odsadapter/ReadRequestHandler.java +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/ReadRequestHandler.java @@ -1,24 +1,29 @@ -/********************************************************************************
- * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information regarding copyright ownership.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- ********************************************************************************/
+/******************************************************************************** + * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ package org.eclipse.mdm.api.odsadapter; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.Set; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.asam.ods.AoException; import org.asam.ods.Column; import org.asam.ods.ElemId; @@ -26,29 +31,111 @@ import org.asam.ods.NameValueSeqUnit; import org.asam.ods.T_LONGLONG; import org.asam.ods.ValueMatrix; import org.asam.ods.ValueMatrixMode; +import org.eclipse.mdm.api.base.adapter.Attribute; +import org.eclipse.mdm.api.base.adapter.EntityType; import org.eclipse.mdm.api.base.massdata.ReadRequest; +import org.eclipse.mdm.api.base.massdata.ReadRequest.ValuesMode; +import org.eclipse.mdm.api.base.model.AxisType; import org.eclipse.mdm.api.base.model.Channel; import org.eclipse.mdm.api.base.model.Entity; import org.eclipse.mdm.api.base.model.MeasuredValues; +import org.eclipse.mdm.api.base.model.SequenceRepresentation; import org.eclipse.mdm.api.base.model.Unit; +import org.eclipse.mdm.api.base.model.Value; +import org.eclipse.mdm.api.base.query.ComparisonOperator; import org.eclipse.mdm.api.base.query.DataAccessException; +import org.eclipse.mdm.api.base.query.Filter; +import org.eclipse.mdm.api.base.query.Query; +import org.eclipse.mdm.api.base.query.QueryService; +import org.eclipse.mdm.api.base.query.Result; import org.eclipse.mdm.api.odsadapter.query.ODSEntityType; import org.eclipse.mdm.api.odsadapter.query.ODSModelManager; import org.eclipse.mdm.api.odsadapter.utils.ODSConverter; +import com.google.common.collect.Lists; + /** * Reads mass data specified in {@link ReadRequest}s. * * @since 1.0.0 * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH */ -final class ReadRequestHandler { +public final class ReadRequestHandler { + public static final class ColumnAttributes + { + private String name; + private SequenceRepresentation sequenceRepresentation; + private double[] generationParameters; + private boolean independent; + private AxisType axisType; + + public ColumnAttributes(String name, SequenceRepresentation sequenceRepresentation, double[] generationParameters, boolean independent, AxisType axisType) + { + this.name = name; + this.sequenceRepresentation = sequenceRepresentation; + this.generationParameters = generationParameters; + this.independent = independent; + this.axisType = axisType; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public SequenceRepresentation getSequenceRepresentation() + { + return sequenceRepresentation; + } + + public void setSequenceRepresentation(SequenceRepresentation sequenceRepresentation) + { + this.sequenceRepresentation = sequenceRepresentation; + } + + public double[] getGenerationParameters() + { + return generationParameters; + } + + public void setGenerationParameters(double[] generationParameters) + { + this.generationParameters = generationParameters; + } + + public boolean isIndependentColumn() + { + return independent; + } + + public void setIndependentColumn(boolean independent) + { + this.independent = independent; + } + + public AxisType getAxisType() + { + return axisType; + } + + public void setAxisType(AxisType axisType) + { + this.axisType = axisType; + } + + } // ====================================================================== // Instance variables // ====================================================================== private final ODSModelManager modelManager; + private final QueryService queryService; // ====================================================================== // Constructors @@ -60,8 +147,9 @@ final class ReadRequestHandler { * @param modelManager * Used to gain access to value matrices. */ - public ReadRequestHandler(ODSModelManager modelManager) { + public ReadRequestHandler(ODSModelManager modelManager, QueryService queryService) { this.modelManager = modelManager; + this.queryService = queryService; } // ====================================================================== @@ -80,18 +168,22 @@ final class ReadRequestHandler { */ public List<MeasuredValues> execute(ReadRequest readRequest) throws DataAccessException { ValueMatrix valueMatrix = null; - Column[] columns = null; + Column[] arrColumns = null; try { valueMatrix = getValueMatrix(readRequest); - columns = getODSColumns(readRequest, valueMatrix); - NameValueSeqUnit[] nvsus = valueMatrix.getValue(columns, readRequest.getStartIndex(), + List<Pair<Column, ColumnAttributes>> listColumnPairs = getODSColumns(readRequest, valueMatrix); + + arrColumns = listColumnPairs.stream().map(Pair::getLeft).toArray(Column[]::new); + ColumnAttributes[] arrColumnAttributes = listColumnPairs.stream().map(Pair::getRight).toArray(ColumnAttributes[]::new); + + NameValueSeqUnit[] nvsus = valueMatrix.getValue(arrColumns, readRequest.getStartIndex(), readRequest.getRequestSize()); - return ODSConverter.fromODSMeasuredValuesSeq(nvsus); + return ODSConverter.fromODSMeasuredValuesSeq(nvsus, arrColumnAttributes); } catch (AoException aoe) { throw new DataAccessException(aoe.reason, aoe); } finally { - releaseColumns(columns); + releaseColumns(arrColumns); releaseValueMatrix(valueMatrix); } } @@ -116,36 +208,120 @@ final class ReadRequestHandler { * @throws DataAccessException * Thrown on wrong {@code ReadRequest} setup. */ - private Column[] getODSColumns(ReadRequest readRequest, ValueMatrix valueMatrix) + private List<Pair<Column, ColumnAttributes>> getODSColumns(ReadRequest readRequest, ValueMatrix valueMatrix) throws AoException, DataAccessException { - if (readRequest.isLoadAllChannels()) { - // TODO should it be possible to overwrite the unit of some - // channels?! - // -> this results in a performance issue since we need to call - // getName() - // on each column for mapping! - return valueMatrix.getColumns("*"); - } + List<Pair<Column, ColumnAttributes>> listColumnPairs = new ArrayList<>(); + Map<String, Column> mapColumns = new HashMap<>(); - List<Column> columnList = new ArrayList<>(); try { - for (Entry<Channel, Unit> entry : readRequest.getChannels().entrySet()) { - Channel channel = entry.getKey(); - Unit unit = entry.getValue(); - Column[] columns = valueMatrix.getColumns(channel.getName()); - if (columns == null || columns.length != 1) { - releaseColumns(columns); - throw new DataAccessException("Column with name '" + channel.getName() + "' not found."); + if (readRequest.isLoadAllChannels()) { + // TODO should it be possible to overwrite the unit of some + // channels?! + // -> this results in a performance issue since we need to call + // getName() + // on each column for mapping! (no longer, see below!) + Column[] columns = valueMatrix.getColumns("*"); + + if (null != columns) { + for (Column column : columns) { + String columnName = column.getName(); + if (mapColumns.containsKey(columnName)) + { + releaseColumns(columns); + throw new DataAccessException(String.format("Duplicate column name '%s' found within submatrix ID %d!", + columnName, Long.valueOf(readRequest.getChannelGroup().getID()))); + } + + mapColumns.put(columnName, column); + } + } + } else { + for (Entry<Channel, Unit> entry : readRequest.getChannels().entrySet()) { + Channel channel = entry.getKey(); + Unit unit = entry.getValue(); + String channelName = channel.getName(); + Column[] columns = valueMatrix.getColumns(channelName); + if (columns == null || columns.length != 1) { + releaseColumns(columns); + throw new DataAccessException(String.format("Zero or more than one column with name '%s' found within submatrix ID %d!", + channelName, Long.valueOf(readRequest.getChannelGroup().getID()))); + } + + Column column = columns[0]; + if (!unit.nameEquals(channel.getUnit().getName())) { + column.setUnit(unit.getName()); + } + + mapColumns.put(channelName, column); + } + } + + if (mapColumns.size() > 0) { + EntityType localColumnEntityType = modelManager.getEntityType("LocalColumn"); + Attribute idAttr = localColumnEntityType.getAttribute("Id"); + Attribute nameAttr = localColumnEntityType.getAttribute("Name"); + Attribute submatrixAttr = localColumnEntityType.getAttribute("SubMatrix"); + + // Don't query GenerationParameters together with other non-ID attributes as Avalon dislikes this: + Query query1 = queryService.createQuery() + .select(Lists.newArrayList(idAttr, + nameAttr, + localColumnEntityType.getAttribute("SequenceRepresentation"), + localColumnEntityType.getAttribute("IndependentFlag"), + localColumnEntityType.getAttribute("axistype"))); + + + + Filter filter = Filter.and() + .add(ComparisonOperator.EQUAL.create(submatrixAttr, Long.valueOf(readRequest.getChannelGroup().getID()))); + + Set<String> setColumnNames = mapColumns.keySet(); + + Map<Long, ColumnAttributes> mapColumnAttributes = new HashMap<>(); + + for (Result result : query1.fetch(filter)) { + Map<String, Value> mapValues = result.getRecord(localColumnEntityType).getValues(); + + String columnName = mapValues.get("Name").extract(); + + if (setColumnNames.contains(columnName)) + { + ColumnAttributes ca = new ColumnAttributes(columnName, + (ValuesMode.CALCULATED == readRequest.getValuesMode() ? SequenceRepresentation.EXPLICIT : mapValues.get("SequenceRepresentation").extract()), + new double[0], + ((short) mapValues.get("IndependentFlag").extract() != 0), + mapValues.get("axistype").extract()); + + mapColumnAttributes.put(mapValues.get("Id").extract(), ca); + } + } + + if (ValuesMode.CALCULATED != readRequest.getValuesMode()) + { + Query query2 = queryService.createQuery() + .select(idAttr, + localColumnEntityType.getAttribute("GenerationParameters")); + + for (Result result : query2.fetch(filter)) { + Map<String, Value> mapValues = result.getRecord(localColumnEntityType).getValues(); + + ColumnAttributes ca = mapColumnAttributes.get(mapValues.get("Id").extract()); + + if (ca != null) { + ca.setGenerationParameters(mapValues.get("GenerationParameters").extract()); + } + } } - Column column = columns[0]; - if (!unit.nameEquals(channel.getUnit().getName())) { - column.setUnit(unit.getName()); + + for (Map.Entry<Long, ColumnAttributes> me : mapColumnAttributes.entrySet()) { + ColumnAttributes ca = me.getValue(); + listColumnPairs.add(new ImmutablePair<Column, ColumnAttributes>(mapColumns.get(ca.getName()), ca)); } - columnList.add(column); } - return columnList.toArray(new Column[columnList.size()]); + + return listColumnPairs; } catch (AoException e) { - releaseColumns(columnList.toArray(new Column[columnList.size()])); + releaseColumns(listColumnPairs.stream().map(Pair::getLeft).toArray(Column[]::new)); throw new DataAccessException("Unable to load column due to: " + e.reason, e); } } @@ -164,7 +340,17 @@ final class ReadRequestHandler { Entity entity = readRequest.getChannelGroup(); T_LONGLONG iid = ODSConverter.toODSID(entity.getID()); T_LONGLONG aid = ((ODSEntityType) modelManager.getEntityType(entity)).getODSID(); - return modelManager.getApplElemAccess().getValueMatrixInMode(new ElemId(aid, iid), ValueMatrixMode.CALCULATED); + ValueMatrixMode valueMatrixMode = ValueMatrixMode.CALCULATED; + switch (readRequest.getValuesMode()) + { + case CALCULATED: valueMatrixMode = ValueMatrixMode.CALCULATED; break; + case STORAGE: valueMatrixMode = ValueMatrixMode.STORAGE; break; + default: + throw new DataAccessException( + String.format("Unsupported ValueMode %s!", readRequest.getValuesMode().name())); + } + + return modelManager.getApplElemAccess().getValueMatrixInMode(new ElemId(aid, iid), valueMatrixMode); } /** diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java b/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java new file mode 100644 index 0000000..5f17e54 --- /dev/null +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java @@ -0,0 +1,336 @@ +/******************************************************************************** + * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ + +package org.eclipse.mdm.api.odsadapter.lookup.config; + +import java.util.Locale; + +import org.eclipse.mdm.api.base.adapter.EntityType; +import org.eclipse.mdm.api.base.adapter.Relation; +import org.eclipse.mdm.api.base.model.Channel; +import org.eclipse.mdm.api.base.model.ChannelGroup; +import org.eclipse.mdm.api.base.model.ContextComponent; +import org.eclipse.mdm.api.base.model.ContextRoot; +import org.eclipse.mdm.api.base.model.ContextSensor; +import org.eclipse.mdm.api.base.model.ContextType; +import org.eclipse.mdm.api.base.model.Entity; +import org.eclipse.mdm.api.base.model.Environment; +import org.eclipse.mdm.api.base.model.Measurement; +import org.eclipse.mdm.api.base.model.Parameter; +import org.eclipse.mdm.api.base.model.ParameterSet; +import org.eclipse.mdm.api.base.model.PhysicalDimension; +import org.eclipse.mdm.api.base.model.Quantity; +import org.eclipse.mdm.api.base.model.Sortable; +import org.eclipse.mdm.api.base.model.Test; +import org.eclipse.mdm.api.base.model.TestStep; +import org.eclipse.mdm.api.base.model.Unit; +import org.eclipse.mdm.api.base.model.User; +import org.eclipse.mdm.api.dflt.model.CatalogAttribute; +import org.eclipse.mdm.api.dflt.model.CatalogComponent; +import org.eclipse.mdm.api.dflt.model.CatalogSensor; +import org.eclipse.mdm.api.dflt.model.Pool; +import org.eclipse.mdm.api.dflt.model.Project; +import org.eclipse.mdm.api.dflt.model.Role; +import org.eclipse.mdm.api.dflt.model.TemplateAttribute; +import org.eclipse.mdm.api.dflt.model.TemplateComponent; +import org.eclipse.mdm.api.dflt.model.TemplateRoot; +import org.eclipse.mdm.api.dflt.model.TemplateSensor; +import org.eclipse.mdm.api.dflt.model.TemplateTest; +import org.eclipse.mdm.api.dflt.model.TemplateTestStep; +import org.eclipse.mdm.api.dflt.model.TemplateTestStepUsage; +import org.eclipse.mdm.api.dflt.model.ValueList; +import org.eclipse.mdm.api.dflt.model.ValueListValue; +import org.eclipse.mdm.api.dflt.model.Versionable; +import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key; +import org.eclipse.mdm.api.odsadapter.query.ODSEntityType; +import org.eclipse.mdm.api.odsadapter.query.ODSModelManager; +import org.eclipse.mdm.api.odsadapter.utils.ODSUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DefaultEntityConfigRepositoryLoader implements EntityConfigRepositoryLoader { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultEntityConfigRepositoryLoader.class); + + EntityConfigRepository entityConfigRepository; + + + public DefaultEntityConfigRepositoryLoader() { + } + + /** + * Loads the {@link EntityConfig}s. + * @return + */ + @Override + public EntityConfigRepository loadEntityConfigurations(ODSModelManager modelManager) { + LOGGER.debug("Loading entity configurations..."); + long start = System.currentTimeMillis(); + + entityConfigRepository = new EntityConfigRepository(); + + entityConfigRepository.register(create(modelManager, new Key<>(Role.class), "Role", false)); + + // Environment | Project | Pool | PhysicalDimension | User | Measurement + // | ChannelGroup + entityConfigRepository.register(create(modelManager, new Key<>(Environment.class), "Environment", false)); + entityConfigRepository.register(create(modelManager, new Key<>(Project.class), "Project", false)); + entityConfigRepository.register(create(modelManager, new Key<>(Pool.class), "StructureLevel", true)); + entityConfigRepository.register(create(modelManager, new Key<>(PhysicalDimension.class), "PhysDimension", false)); + entityConfigRepository.register(create(modelManager, new Key<>(User.class), "User", false)); + entityConfigRepository.register(create(modelManager, new Key<>(Measurement.class), "MeaResult", false)); + entityConfigRepository.register(create(modelManager, new Key<>(ChannelGroup.class), "SubMatrix", false)); + + // Unit + EntityConfig<Unit> unitConfig = create(modelManager, new Key<>(Unit.class), "Unit", false); + unitConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(PhysicalDimension.class))); + entityConfigRepository.register(unitConfig); + + // Quantity + EntityConfig<Quantity> quantityConfig = create(modelManager, new Key<>(Quantity.class), "Quantity", false); + quantityConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(Unit.class))); + entityConfigRepository.register(quantityConfig); + + // Channel + EntityConfig<Channel> channelConfig = create(modelManager, new Key<>(Channel.class), "MeaQuantity", false); + channelConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(Unit.class))); + channelConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(Quantity.class))); + entityConfigRepository.register(channelConfig); + + // ValueList + EntityConfig<ValueListValue> valueListValueConfig = create(modelManager, new Key<>(ValueListValue.class), "ValueListValue", + true); + valueListValueConfig.setComparator(Sortable.COMPARATOR); + EntityConfig<ValueList> valueListConfig = create(modelManager, new Key<>(ValueList.class), "ValueList", true); + valueListConfig.addChild(valueListValueConfig); + entityConfigRepository.register(valueListConfig); + + // ParameterSet + EntityConfig<Parameter> parameterConfig = create(modelManager, new Key<>(Parameter.class), "ResultParameter", true); + parameterConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Unit.class))); + EntityConfig<ParameterSet> parameterSetConfig = create(modelManager, new Key<>(ParameterSet.class), "ResultParameterSet", + true); + parameterSetConfig.addChild(parameterConfig); + entityConfigRepository.register(parameterSetConfig); + + // CatalogComponents + registerCatalogComponent(modelManager, ContextType.UNITUNDERTEST); + registerCatalogComponent(modelManager, ContextType.TESTSEQUENCE); + registerCatalogComponent(modelManager, ContextType.TESTEQUIPMENT); + + // TemplateRoots + registerTemplateRoot(modelManager, ContextType.UNITUNDERTEST); + registerTemplateRoot(modelManager, ContextType.TESTSEQUENCE); + registerTemplateRoot(modelManager, ContextType.TESTEQUIPMENT); + + // TemplateTestStep + EntityConfig<TemplateTestStep> templateTestStepConfig = create(modelManager, new Key<>(TemplateTestStep.class), "TplTestStep", + true); + templateTestStepConfig + .addOptional(entityConfigRepository.findRoot(new Key<>(TemplateRoot.class, ContextType.UNITUNDERTEST))); + templateTestStepConfig + .addOptional(entityConfigRepository.findRoot(new Key<>(TemplateRoot.class, ContextType.TESTSEQUENCE))); + templateTestStepConfig + .addOptional(entityConfigRepository.findRoot(new Key<>(TemplateRoot.class, ContextType.TESTEQUIPMENT))); + templateTestStepConfig.setComparator(Versionable.COMPARATOR); + entityConfigRepository.register(templateTestStepConfig); + + // Status TestStep + // TODO check MIME type genration + // entityConfigRepository.register(create(new Key<>(Status.class, + // TestStep.class), "StatusTestStep", true)); + + // TestStep + EntityConfig<TestStep> testStepConfig = create(modelManager, new Key<>(TestStep.class), "TestStep", true); + // testStepConfig.addMandatory(entityConfigRepository.findRoot(new + // Key<>(Status.class, TestStep.class))); + testStepConfig.addOptional(entityConfigRepository.findRoot(new Key<>(TemplateTestStep.class))); + testStepConfig.setComparator(Sortable.COMPARATOR); + entityConfigRepository.register(testStepConfig); + + // TemplateTest + EntityConfig<TemplateTestStepUsage> templateTestStepUsageConfig = create(modelManager, new Key<>(TemplateTestStepUsage.class), + "TplTestStepUsage", true); + templateTestStepUsageConfig.addMandatory(templateTestStepConfig); + templateTestStepUsageConfig.setComparator(Sortable.COMPARATOR); + EntityConfig<TemplateTest> templateTestConfig = create(modelManager, new Key<>(TemplateTest.class), "TplTest", true); + templateTestConfig.addChild(templateTestStepUsageConfig); + templateTestConfig.setComparator(Versionable.COMPARATOR); + entityConfigRepository.register(templateTestConfig); + + // Status Test + // TODO check MIME type genration + // entityConfigRepository.register(create(new Key<>(Status.class, + // Test.class), "StatusTest", true)); + + // Test + EntityConfig<Test> testConfig = create(modelManager, new Key<>(Test.class), "Test", true); + testConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(User.class))); + // testConfig.addMandatory(entityConfigRepository.findRoot(new + // Key<>(Status.class, Test.class))); + testConfig.addOptional(entityConfigRepository.findRoot(new Key<>(TemplateTest.class))); + entityConfigRepository.register(testConfig); + + // ContextRoots + registerContextRoot(modelManager, ContextType.UNITUNDERTEST); + registerContextRoot(modelManager, ContextType.TESTSEQUENCE); + registerContextRoot(modelManager, ContextType.TESTEQUIPMENT); + + LOGGER.debug("Entity configurations loaded in {} ms.", System.currentTimeMillis() - start); + return entityConfigRepository; + } + + /** + * Loads the {@link EntityConfig}s required for {@link ContextRoot} with + * given {@link ContextType}. + * + * @param contextType + * The {@code ContextType}. + */ + private void registerContextRoot(ODSModelManager modelManager, ContextType contextType) { + EntityConfig<ContextRoot> contextRootConfig = create(modelManager, new Key<>(ContextRoot.class, contextType), + ODSUtils.CONTEXTTYPES.get(contextType), true); + contextRootConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(TemplateRoot.class, contextType))); + for (Relation contextComponentRelation : contextRootConfig.getEntityType().getChildRelations()) { + EntityType contextComponentEntityType = contextComponentRelation.getTarget(); + EntityConfig<ContextComponent> contextComponentConfig = create(modelManager, + new Key<>(ContextComponent.class, contextType), contextComponentEntityType.getName(), true); + contextComponentConfig + .addInherited(entityConfigRepository.findImplicit(new Key<>(TemplateComponent.class, contextType))); + contextRootConfig.addChild(contextComponentConfig); + if (contextType.isTestEquipment()) { + for (Relation contextSensorRelation : contextComponentEntityType.getChildRelations()) { + EntityType contextSensorEntityType = contextSensorRelation.getTarget(); + EntityConfig<ContextSensor> contextSensorConfig = create(modelManager, new Key<>(ContextSensor.class), + contextSensorEntityType.getName(), true); + contextSensorConfig + .addInherited(entityConfigRepository.findImplicit(new Key<>(TemplateSensor.class))); + contextComponentConfig.addChild(contextSensorConfig); + } + } + } + entityConfigRepository.register(contextRootConfig); + } + + /** + * Loads the {@link EntityConfig}s required for {@link TemplateRoot} with + * given {@link ContextType}. + * + * @param contextType + * The {@code ContextType}. + */ + private void registerTemplateRoot(ODSModelManager modelManager, ContextType contextType) { + String odsName = ODSUtils.CONTEXTTYPES.get(contextType); + EntityConfig<TemplateAttribute> templateAttributeConfig = create(modelManager, + new Key<>(TemplateAttribute.class, contextType), "Tpl" + odsName + "Attr", true); + templateAttributeConfig + .addInherited(entityConfigRepository.findImplicit(new Key<>(CatalogAttribute.class, contextType))); + templateAttributeConfig.setComparator(TemplateAttribute.COMPARATOR); + EntityConfig<TemplateComponent> templateComponentConfig = create(modelManager, + new Key<>(TemplateComponent.class, contextType), "Tpl" + odsName + "Comp", true); + templateComponentConfig.addChild(templateAttributeConfig); + templateComponentConfig + .addMandatory(entityConfigRepository.findRoot(new Key<>(CatalogComponent.class, contextType))); + templateComponentConfig.addChild(templateComponentConfig); + templateComponentConfig.setComparator(Sortable.COMPARATOR); + if (contextType.isTestEquipment()) { + EntityConfig<TemplateAttribute> templateSensorAttributeConfig = create(modelManager, new Key<>(TemplateAttribute.class), + "TplSensorAttr", true); + templateSensorAttributeConfig.setComparator(TemplateAttribute.COMPARATOR); + templateSensorAttributeConfig + .addInherited(entityConfigRepository.findImplicit(new Key<>(CatalogAttribute.class))); + EntityConfig<TemplateSensor> templateSensorConfig = create(modelManager, new Key<>(TemplateSensor.class), "TplSensor", + true); + templateSensorConfig.addChild(templateSensorAttributeConfig); + templateSensorConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(Quantity.class))); + templateSensorConfig.addInherited(entityConfigRepository.findImplicit(new Key<>(CatalogSensor.class))); + templateSensorConfig.setComparator(Sortable.COMPARATOR); + templateComponentConfig.addChild(templateSensorConfig); + } + EntityConfig<TemplateRoot> templateRootConfig = create(modelManager, new Key<>(TemplateRoot.class, contextType), + "Tpl" + odsName + "Root", true); + templateRootConfig.addChild(templateComponentConfig); + templateRootConfig.setComparator(Versionable.COMPARATOR); + entityConfigRepository.register(templateRootConfig); + } + + /** + * Loads the {@link EntityConfig}s required for {@link CatalogComponent} + * with given {@link ContextType}. + * + * @param contextType + * The {@code ContextType}. + */ + private void registerCatalogComponent(ODSModelManager modelManager, ContextType contextType) { + String odsName = ODSUtils.CONTEXTTYPES.get(contextType); + EntityConfig<CatalogAttribute> catalogAttributeConfig = create(modelManager, new Key<>(CatalogAttribute.class, contextType), + "Cat" + odsName + "Attr", true); + catalogAttributeConfig.addOptional(entityConfigRepository.findRoot(new Key<>(ValueList.class))); + catalogAttributeConfig.setComparator(Sortable.COMPARATOR); + EntityConfig<CatalogComponent> catalogComponentConfig = create(modelManager, new Key<>(CatalogComponent.class, contextType), + "Cat" + odsName + "Comp", true); + catalogComponentConfig.addChild(catalogAttributeConfig); + if (contextType.isTestEquipment()) { + EntityConfig<CatalogAttribute> catalogSensorAttributeConfig = create(modelManager, new Key<>(CatalogAttribute.class), + "CatSensorAttr", true); + catalogSensorAttributeConfig.addOptional(entityConfigRepository.findRoot(new Key<>(ValueList.class))); + EntityConfig<CatalogSensor> catalogSensorConfig = create(modelManager, new Key<>(CatalogSensor.class), "CatSensor", true); + catalogSensorConfig.addChild(catalogSensorAttributeConfig); + catalogComponentConfig.addChild(catalogSensorConfig); + } + entityConfigRepository.register(catalogComponentConfig); + } + + /** + * Creates a new {@link EntityConfig}. + * + * @param <T> + * The entity type. + * @param key + * Used as identifier. + * @param typeName + * Name of the associated {@link EntityType}. + * @param appendName + * Flag indicates whether to append the entity types base name to + * the MIME type. + * @return The created {@code EntityConfig} is returned. + */ + private <T extends Entity> EntityConfig<T> create(ODSModelManager modelManager, Key<T> key, String typeName, boolean appendName) { + EntityConfig<T> entityConfig = new EntityConfig<>(key); + ODSEntityType entityType = (ODSEntityType) modelManager.getEntityType(typeName); + entityConfig.setEntityType(entityType); + entityConfig.setMimeType(buildDefaultMimeType(entityType, appendName)); + return entityConfig; + } + + /** + * Creates a default MIME type for given {@link EntityType}. + * + * @param entityType + * The {@code EntityType}. + * @param appendName + * Flag indicates whether to append the entity types base name to + * the MIME type. + * @return The created MIME type {@code String} is returned. + */ + private String buildDefaultMimeType(ODSEntityType entityType, boolean appendName) { + StringBuilder sb = new StringBuilder(); + sb.append("application/x-asam."); + sb.append(entityType.getBaseName().toLowerCase(Locale.ROOT)); + if (appendName) { + sb.append('.').append(entityType.getName().toLowerCase(Locale.ROOT)); + } + return sb.toString(); + } +} diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/EntityConfigRepositoryLoader.java b/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/EntityConfigRepositoryLoader.java new file mode 100644 index 0000000..80b205d --- /dev/null +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/EntityConfigRepositoryLoader.java @@ -0,0 +1,26 @@ +/******************************************************************************** + * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ + +package org.eclipse.mdm.api.odsadapter.lookup.config; + +import org.eclipse.mdm.api.odsadapter.query.ODSModelManager; + +public interface EntityConfigRepositoryLoader { + + /** + * Loads the {@link EntityConfigRepository}. + * @return + */ + EntityConfigRepository loadEntityConfigurations(ODSModelManager modelManager); +} diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSEntityFactory.java b/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSEntityFactory.java index c66516f..14d5d19 100644 --- a/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSEntityFactory.java +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSEntityFactory.java @@ -1,16 +1,16 @@ -/********************************************************************************
- * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information regarding copyright ownership.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- ********************************************************************************/
+/******************************************************************************** + * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ package org.eclipse.mdm.api.odsadapter.query; @@ -76,7 +76,7 @@ public final class ODSEntityFactory extends EntityFactory { // ====================================================================== private final ODSModelManager modelManager; - private final User loggedInUser; + private final Optional<User> loggedInUser; // ====================================================================== // Constructors @@ -90,7 +90,7 @@ public final class ODSEntityFactory extends EntityFactory { * @param loggedInUser * The logged in {@link User}. */ - public ODSEntityFactory(ODSModelManager modelManager, User loggedInUser) { + public ODSEntityFactory(ODSModelManager modelManager, Optional<User> loggedInUser) { this.modelManager = modelManager; this.loggedInUser = loggedInUser; } @@ -153,7 +153,7 @@ public final class ODSEntityFactory extends EntityFactory { */ @Override protected Optional<User> getLoggedInUser() { - return Optional.of(loggedInUser); + return loggedInUser; } /** diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java b/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java index 6efe7f3..b1e9b07 100644 --- a/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.concurrent.locks.Lock; @@ -49,52 +48,19 @@ import org.asam.ods.T_LONGLONG; import org.eclipse.mdm.api.base.adapter.EntityType; import org.eclipse.mdm.api.base.adapter.ModelManager; import org.eclipse.mdm.api.base.adapter.Relation; -import org.eclipse.mdm.api.base.model.Channel; -import org.eclipse.mdm.api.base.model.ChannelGroup; -import org.eclipse.mdm.api.base.model.ContextComponent; -import org.eclipse.mdm.api.base.model.ContextRoot; -import org.eclipse.mdm.api.base.model.ContextSensor; import org.eclipse.mdm.api.base.model.ContextType; import org.eclipse.mdm.api.base.model.Entity; import org.eclipse.mdm.api.base.model.EnumRegistry; import org.eclipse.mdm.api.base.model.Enumeration; -import org.eclipse.mdm.api.base.model.Environment; -import org.eclipse.mdm.api.base.model.Measurement; -import org.eclipse.mdm.api.base.model.Parameter; -import org.eclipse.mdm.api.base.model.ParameterSet; -import org.eclipse.mdm.api.base.model.PhysicalDimension; -import org.eclipse.mdm.api.base.model.Quantity; -import org.eclipse.mdm.api.base.model.Sortable; -import org.eclipse.mdm.api.base.model.Test; -import org.eclipse.mdm.api.base.model.TestStep; import org.eclipse.mdm.api.base.model.Unit; -import org.eclipse.mdm.api.base.model.User; -import org.eclipse.mdm.api.dflt.model.CatalogAttribute; -import org.eclipse.mdm.api.dflt.model.CatalogComponent; -import org.eclipse.mdm.api.dflt.model.CatalogSensor; -import org.eclipse.mdm.api.dflt.model.Classification; -import org.eclipse.mdm.api.dflt.model.Domain; -import org.eclipse.mdm.api.dflt.model.Pool; -import org.eclipse.mdm.api.dflt.model.Project; -import org.eclipse.mdm.api.dflt.model.ProjectDomain; -import org.eclipse.mdm.api.dflt.model.Status; -import org.eclipse.mdm.api.dflt.model.TemplateAttribute; -import org.eclipse.mdm.api.dflt.model.TemplateComponent; -import org.eclipse.mdm.api.dflt.model.TemplateRoot; -import org.eclipse.mdm.api.dflt.model.TemplateSensor; -import org.eclipse.mdm.api.dflt.model.TemplateTest; -import org.eclipse.mdm.api.dflt.model.TemplateTestStep; -import org.eclipse.mdm.api.dflt.model.TemplateTestStepUsage; -import org.eclipse.mdm.api.dflt.model.ValueList; -import org.eclipse.mdm.api.dflt.model.ValueListValue; -import org.eclipse.mdm.api.dflt.model.Versionable; +import org.eclipse.mdm.api.odsadapter.lookup.config.DefaultEntityConfigRepositoryLoader; import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig; import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key; import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfigRepository; +import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfigRepositoryLoader; import org.eclipse.mdm.api.odsadapter.utils.ODSConverter; import org.eclipse.mdm.api.odsadapter.utils.ODSEnum; import org.eclipse.mdm.api.odsadapter.utils.ODSEnumerations; -import org.eclipse.mdm.api.odsadapter.utils.ODSUtils; import org.omg.CORBA.ORB; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -118,6 +84,7 @@ public class ODSModelManager implements ModelManager { private final Lock read; private EntityConfigRepository entityConfigRepository; + private EntityConfigRepositoryLoader entityConfigRepositoryLoader; private ApplElemAccess applElemAccess; private AoSession aoSession; @@ -133,10 +100,25 @@ public class ODSModelManager implements ModelManager { * Thrown on errors. */ public ODSModelManager(ORB orb, AoSession aoSession) throws AoException { + this(orb, aoSession, new DefaultEntityConfigRepositoryLoader()); + } + + /** + * Constructor. + * + * @param orb + * Used to activate CORBA service objects. + * @param aoSession + * The underlying ODS session. + * @throws AoException + * Thrown on errors. + */ + public ODSModelManager(ORB orb, AoSession aoSession, EntityConfigRepositoryLoader entityConfigRepositoryLoader) throws AoException { this.aoSession = aoSession; this.orb = orb; applElemAccess = aoSession.getApplElemAccess(); - + this.entityConfigRepositoryLoader = entityConfigRepositoryLoader; + // setup locks ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(); write = reentrantReadWriteLock.writeLock(); @@ -368,7 +350,7 @@ public class ODSModelManager implements ModelManager { */ private void initialize() throws AoException { loadApplicationModel(); - loadEntityConfigurations(); + entityConfigRepository = entityConfigRepositoryLoader.loadEntityConfigurations(this); } /** @@ -428,7 +410,7 @@ public class ODSModelManager implements ModelManager { EnumerationDefinition bubu = applicationStructure.getEnumerationDefinition(eas.enumName); for (String itemName : bubu.listItemNames()) { final int intValue = bubu.getItem(itemName); - LOGGER.debug("{}:{}:{}", eas.enumName, itemName, intValue); + LOGGER.trace("{}:{}:{}", eas.enumName, itemName, intValue); } // make sure the enumeration is found @@ -482,284 +464,4 @@ public class ODSModelManager implements ModelManager { return units; } - - /** - * Loads the {@link EntityConfig}s. - */ - private void loadEntityConfigurations() { - LOGGER.debug("Loading entity configurations..."); - long start = System.currentTimeMillis(); - - entityConfigRepository = new EntityConfigRepository(); - - // Environment | Project | Pool | PhysicalDimension | User | Measurement - // | ChannelGroup - entityConfigRepository.register(create(new Key<>(Environment.class), "Environment", false)); - entityConfigRepository.register(create(new Key<>(Project.class), "Project", false)); - entityConfigRepository.register(create(new Key<>(Pool.class), "StructureLevel", true)); - entityConfigRepository.register(create(new Key<>(PhysicalDimension.class), "PhysDimension", false)); - entityConfigRepository.register(create(new Key<>(User.class), "User", false)); - entityConfigRepository.register(create(new Key<>(ChannelGroup.class), "SubMatrix", false)); - entityConfigRepository.register(create(new Key<>(Status.class), "Status", true)); - - // Project Domain - EntityConfig<ProjectDomain> projectDomainEntityConfig = create(new Key<>(ProjectDomain.class), "ProjectDomain", true); - entityConfigRepository.register(projectDomainEntityConfig); - - // Domain - EntityConfig<Domain> domainEntityConfig = create(new Key<>(Domain.class), "Domain", true); - entityConfigRepository.register(domainEntityConfig); - - // Classification - EntityConfig<Classification> classificationEntityConfig = create(new Key<>(Classification.class), "Classification", true); - classificationEntityConfig.addOptional(entityConfigRepository.findRoot(new Key<>(ProjectDomain.class))); - classificationEntityConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Domain.class))); - classificationEntityConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Status.class))); - entityConfigRepository.register(classificationEntityConfig); - - EntityConfig<Measurement> measurementEntityConfig = create(new Key<>(Measurement.class), "MeaResult", false); - measurementEntityConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Classification.class))); - entityConfigRepository.register(measurementEntityConfig); - - // Unit - EntityConfig<Unit> unitConfig = create(new Key<>(Unit.class), "Unit", false); - unitConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(PhysicalDimension.class))); - entityConfigRepository.register(unitConfig); - - // Quantity - EntityConfig<Quantity> quantityConfig = create(new Key<>(Quantity.class), "Quantity", false); - quantityConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(Unit.class))); - entityConfigRepository.register(quantityConfig); - - // Channel - EntityConfig<Channel> channelConfig = create(new Key<>(Channel.class), "MeaQuantity", false); - channelConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(Unit.class))); - channelConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(Quantity.class))); - entityConfigRepository.register(channelConfig); - - // ValueList - EntityConfig<ValueListValue> valueListValueConfig = create(new Key<>(ValueListValue.class), "ValueListValue", - true); - valueListValueConfig.setComparator(Sortable.COMPARATOR); - EntityConfig<ValueList> valueListConfig = create(new Key<>(ValueList.class), "ValueList", true); - valueListConfig.addChild(valueListValueConfig); - entityConfigRepository.register(valueListConfig); - - // ParameterSet - EntityConfig<Parameter> parameterConfig = create(new Key<>(Parameter.class), "ResultParameter", true); - parameterConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Unit.class))); - EntityConfig<ParameterSet> parameterSetConfig = create(new Key<>(ParameterSet.class), "ResultParameterSet", - true); - parameterSetConfig.addChild(parameterConfig); - entityConfigRepository.register(parameterSetConfig); - - // CatalogComponents - registerCatalogComponent(ContextType.UNITUNDERTEST); - registerCatalogComponent(ContextType.TESTSEQUENCE); - registerCatalogComponent(ContextType.TESTEQUIPMENT); - - // TemplateRoots - registerTemplateRoot(ContextType.UNITUNDERTEST); - registerTemplateRoot(ContextType.TESTSEQUENCE); - registerTemplateRoot(ContextType.TESTEQUIPMENT); - - // TemplateTestStep - EntityConfig<TemplateTestStep> templateTestStepConfig = create(new Key<>(TemplateTestStep.class), "TplTestStep", - true); - templateTestStepConfig - .addOptional(entityConfigRepository.findRoot(new Key<>(TemplateRoot.class, ContextType.UNITUNDERTEST))); - templateTestStepConfig - .addOptional(entityConfigRepository.findRoot(new Key<>(TemplateRoot.class, ContextType.TESTSEQUENCE))); - templateTestStepConfig - .addOptional(entityConfigRepository.findRoot(new Key<>(TemplateRoot.class, ContextType.TESTEQUIPMENT))); - templateTestStepConfig.setComparator(Versionable.COMPARATOR); - entityConfigRepository.register(templateTestStepConfig); - - // Status TestStep - // TODO check MIME type genration - // entityConfigRepository.register(create(new Key<>(Status.class, - // TestStep.class), "StatusTestStep", true)); - - // TestStep - EntityConfig<TestStep> testStepConfig = create(new Key<>(TestStep.class), "TestStep", true); - // testStepConfig.addMandatory(entityConfigRepository.findRoot(new - // Key<>(Status.class, TestStep.class))); - testStepConfig.addOptional(entityConfigRepository.findRoot(new Key<>(TemplateTestStep.class))); - testStepConfig.setComparator(Sortable.COMPARATOR); - entityConfigRepository.register(testStepConfig); - - // TemplateTest - EntityConfig<TemplateTestStepUsage> templateTestStepUsageConfig = create(new Key<>(TemplateTestStepUsage.class), - "TplTestStepUsage", true); - templateTestStepUsageConfig.addMandatory(templateTestStepConfig); - templateTestStepUsageConfig.setComparator(Sortable.COMPARATOR); - EntityConfig<TemplateTest> templateTestConfig = create(new Key<>(TemplateTest.class), "TplTest", true); - templateTestConfig.addChild(templateTestStepUsageConfig); - templateTestConfig.setComparator(Versionable.COMPARATOR); - entityConfigRepository.register(templateTestConfig); - - // Status Test - // TODO check MIME type genration - // entityConfigRepository.register(create(new Key<>(Status.class, - // Test.class), "StatusTest", true)); - - // Test - EntityConfig<Test> testConfig = create(new Key<>(Test.class), "Test", true); - testConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(User.class))); - // testConfig.addMandatory(entityConfigRepository.findRoot(new - // Key<>(Status.class, Test.class))); - testConfig.addOptional(entityConfigRepository.findRoot(new Key<>(TemplateTest.class))); - entityConfigRepository.register(testConfig); - - // ContextRoots - registerContextRoot(ContextType.UNITUNDERTEST); - registerContextRoot(ContextType.TESTSEQUENCE); - registerContextRoot(ContextType.TESTEQUIPMENT); - - LOGGER.debug("Entity configurations loaded in {} ms.", System.currentTimeMillis() - start); - } - - /** - * Loads the {@link EntityConfig}s required for {@link ContextRoot} with - * given {@link ContextType}. - * - * @param contextType - * The {@code ContextType}. - */ - private void registerContextRoot(ContextType contextType) { - EntityConfig<ContextRoot> contextRootConfig = create(new Key<>(ContextRoot.class, contextType), - ODSUtils.CONTEXTTYPES.get(contextType), true); - contextRootConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(TemplateRoot.class, contextType))); - for (Relation contextComponentRelation : contextRootConfig.getEntityType().getChildRelations()) { - EntityType contextComponentEntityType = contextComponentRelation.getTarget(); - EntityConfig<ContextComponent> contextComponentConfig = create( - new Key<>(ContextComponent.class, contextType), contextComponentEntityType.getName(), true); - contextComponentConfig - .addInherited(entityConfigRepository.findImplicit(new Key<>(TemplateComponent.class, contextType))); - contextRootConfig.addChild(contextComponentConfig); - if (contextType.isTestEquipment()) { - for (Relation contextSensorRelation : contextComponentEntityType.getChildRelations()) { - EntityType contextSensorEntityType = contextSensorRelation.getTarget(); - EntityConfig<ContextSensor> contextSensorConfig = create(new Key<>(ContextSensor.class), - contextSensorEntityType.getName(), true); - contextSensorConfig - .addInherited(entityConfigRepository.findImplicit(new Key<>(TemplateSensor.class))); - contextComponentConfig.addChild(contextSensorConfig); - } - } - } - entityConfigRepository.register(contextRootConfig); - } - - /** - * Loads the {@link EntityConfig}s required for {@link TemplateRoot} with - * given {@link ContextType}. - * - * @param contextType - * The {@code ContextType}. - */ - private void registerTemplateRoot(ContextType contextType) { - String odsName = ODSUtils.CONTEXTTYPES.get(contextType); - EntityConfig<TemplateAttribute> templateAttributeConfig = create( - new Key<>(TemplateAttribute.class, contextType), "Tpl" + odsName + "Attr", true); - templateAttributeConfig - .addInherited(entityConfigRepository.findImplicit(new Key<>(CatalogAttribute.class, contextType))); - templateAttributeConfig.setComparator(TemplateAttribute.COMPARATOR); - EntityConfig<TemplateComponent> templateComponentConfig = create( - new Key<>(TemplateComponent.class, contextType), "Tpl" + odsName + "Comp", true); - templateComponentConfig.addChild(templateAttributeConfig); - templateComponentConfig - .addMandatory(entityConfigRepository.findRoot(new Key<>(CatalogComponent.class, contextType))); - templateComponentConfig.addChild(templateComponentConfig); - templateComponentConfig.setComparator(Sortable.COMPARATOR); - if (contextType.isTestEquipment()) { - EntityConfig<TemplateAttribute> templateSensorAttributeConfig = create(new Key<>(TemplateAttribute.class), - "TplSensorAttr", true); - templateSensorAttributeConfig.setComparator(TemplateAttribute.COMPARATOR); - templateSensorAttributeConfig - .addInherited(entityConfigRepository.findImplicit(new Key<>(CatalogAttribute.class))); - EntityConfig<TemplateSensor> templateSensorConfig = create(new Key<>(TemplateSensor.class), "TplSensor", - true); - templateSensorConfig.addChild(templateSensorAttributeConfig); - templateSensorConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(Quantity.class))); - templateSensorConfig.addInherited(entityConfigRepository.findImplicit(new Key<>(CatalogSensor.class))); - templateSensorConfig.setComparator(Sortable.COMPARATOR); - templateComponentConfig.addChild(templateSensorConfig); - } - EntityConfig<TemplateRoot> templateRootConfig = create(new Key<>(TemplateRoot.class, contextType), - "Tpl" + odsName + "Root", true); - templateRootConfig.addChild(templateComponentConfig); - templateRootConfig.setComparator(Versionable.COMPARATOR); - entityConfigRepository.register(templateRootConfig); - } - - /** - * Loads the {@link EntityConfig}s required for {@link CatalogComponent} - * with given {@link ContextType}. - * - * @param contextType - * The {@code ContextType}. - */ - private void registerCatalogComponent(ContextType contextType) { - String odsName = ODSUtils.CONTEXTTYPES.get(contextType); - EntityConfig<CatalogAttribute> catalogAttributeConfig = create(new Key<>(CatalogAttribute.class, contextType), - "Cat" + odsName + "Attr", true); - catalogAttributeConfig.addOptional(entityConfigRepository.findRoot(new Key<>(ValueList.class))); - catalogAttributeConfig.setComparator(Sortable.COMPARATOR); - EntityConfig<CatalogComponent> catalogComponentConfig = create(new Key<>(CatalogComponent.class, contextType), - "Cat" + odsName + "Comp", true); - catalogComponentConfig.addChild(catalogAttributeConfig); - if (contextType.isTestEquipment()) { - EntityConfig<CatalogAttribute> catalogSensorAttributeConfig = create(new Key<>(CatalogAttribute.class), - "CatSensorAttr", true); - catalogSensorAttributeConfig.addOptional(entityConfigRepository.findRoot(new Key<>(ValueList.class))); - EntityConfig<CatalogSensor> catalogSensorConfig = create(new Key<>(CatalogSensor.class), "CatSensor", true); - catalogSensorConfig.addChild(catalogSensorAttributeConfig); - catalogComponentConfig.addChild(catalogSensorConfig); - } - entityConfigRepository.register(catalogComponentConfig); - } - - /** - * Creates a new {@link EntityConfig}. - * - * @param <T> - * The entity type. - * @param key - * Used as identifier. - * @param typeName - * Name of the associated {@link EntityType}. - * @param appendName - * Flag indicates whether to append the entity types base name to - * the MIME type. - * @return The created {@code EntityConfig} is returned. - */ - private <T extends Entity> EntityConfig<T> create(Key<T> key, String typeName, boolean appendName) { - EntityConfig<T> entityConfig = new EntityConfig<>(key); - ODSEntityType entityType = (ODSEntityType) getEntityType(typeName); - entityConfig.setEntityType(entityType); - entityConfig.setMimeType(buildDefaultMimeType(entityType, appendName)); - return entityConfig; - } - - /** - * Creates a default MIME type for given {@link EntityType}. - * - * @param entityType - * The {@code EntityType}. - * @param appendName - * Flag indicates whether to append the entity types base name to - * the MIME type. - * @return The created MIME type {@code String} is returned. - */ - private String buildDefaultMimeType(ODSEntityType entityType, boolean appendName) { - StringBuilder sb = new StringBuilder(); - sb.append("application/x-asam."); - sb.append(entityType.getBaseName().toLowerCase(Locale.ROOT)); - if (appendName) { - sb.append('.').append(entityType.getName().toLowerCase(Locale.ROOT)); - } - return sb.toString(); - } - } diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSRelation.java b/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSRelation.java index a6055c3..a623d0e 100644 --- a/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSRelation.java +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSRelation.java @@ -44,7 +44,7 @@ public final class ODSRelation implements Relation { private final String name; private final int rangeMax; - + private final int invRangeMax; private Attribute attribute; // ====================================================================== @@ -67,6 +67,7 @@ public final class ODSRelation implements Relation { name = applRel.arName; relationType = ODSUtils.RELATIONSHIPS.inverse().get(applRel.arRelationType); rangeMax = applRel.arRelationRange.max; + invRangeMax = applRel.invRelationRange.max; } // ====================================================================== @@ -164,5 +165,10 @@ public final class ODSRelation implements Relation { public boolean isIncoming(RelationType relationType) { return relationType.equals(getRelationType()) && rangeMax == -1; } + + @Override + public boolean isNtoM() { + return relationType == RelationType.INFO && rangeMax == -1 && invRangeMax == -1; + } } diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/InsertStatement.java b/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/InsertStatement.java index 0fc5e90..b7fff30 100644 --- a/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/InsertStatement.java +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/InsertStatement.java @@ -1,16 +1,16 @@ -/********************************************************************************
- * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information regarding copyright ownership.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- ********************************************************************************/
+/******************************************************************************** + * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ package org.eclipse.mdm.api.odsadapter.transaction; @@ -272,14 +272,15 @@ final class InsertStatement extends BaseStatement { EntityType test = getModelManager().getEntityType(Test.class); Relation parentRelation = testStep.getRelation(test); + Attribute attrSortIndex = testStep.getAttribute(Sortable.ATTR_SORT_INDEX); Query query = getQueryService().createQuery().select(parentRelation.getAttribute()) - .select(testStep.getAttribute(Sortable.ATTR_SORT_INDEX), Aggregation.MAXIMUM) + .select(attrSortIndex, Aggregation.MAXIMUM) .group(parentRelation.getAttribute()); Filter filter = Filter.idsOnly(parentRelation, sortIndexTestSteps.keySet()); for (Result result : query.fetch(filter)) { Record record = result.getRecord(testStep); - int sortIndex = (Integer) record.getValues().get(Sortable.ATTR_SORT_INDEX).extract(); + int sortIndex = (Integer) record.getValues().get(ODSConverter.getColumnName(attrSortIndex, Aggregation.MAXIMUM)).extract(); sortIndexTestSteps.remove(record.getID(parentRelation).get()).setIndices(sortIndex + 1); } diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/ODSTransaction.java b/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/ODSTransaction.java index a4bf4b9..3fe7ce2 100644 --- a/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/ODSTransaction.java +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/ODSTransaction.java @@ -1,16 +1,16 @@ -/********************************************************************************
- * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information regarding copyright ownership.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- ********************************************************************************/
+/******************************************************************************** + * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ package org.eclipse.mdm.api.odsadapter.transaction; @@ -18,6 +18,7 @@ package org.eclipse.mdm.api.odsadapter.transaction; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -28,9 +29,13 @@ import java.util.function.Function; import java.util.stream.Collectors; import org.asam.ods.AoException; +import org.asam.ods.ElemId; +import org.asam.ods.SetType; +import org.asam.ods.T_LONGLONG; import org.eclipse.mdm.api.base.Transaction; import org.eclipse.mdm.api.base.adapter.Core; import org.eclipse.mdm.api.base.adapter.EntityType; +import org.eclipse.mdm.api.base.adapter.Relation; import org.eclipse.mdm.api.base.massdata.WriteRequest; import org.eclipse.mdm.api.base.model.Channel; import org.eclipse.mdm.api.base.model.ContextRoot; @@ -49,7 +54,10 @@ import org.eclipse.mdm.api.dflt.model.CatalogSensor; import org.eclipse.mdm.api.dflt.model.TemplateAttribute; import org.eclipse.mdm.api.odsadapter.ODSContext; import org.eclipse.mdm.api.odsadapter.filetransfer.Transfer; +import org.eclipse.mdm.api.odsadapter.query.ODSEntityFactory; +import org.eclipse.mdm.api.odsadapter.query.ODSEntityType; import org.eclipse.mdm.api.odsadapter.query.ODSModelManager; +import org.eclipse.mdm.api.odsadapter.utils.ODSConverter; import org.eclipse.mdm.api.odsadapter.utils.ODSUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -170,13 +178,16 @@ public final class ODSTransaction implements Transaction { List<Measurement> measurements = (List<Measurement>) entitiesByClassType.get(Measurement.class); if (measurements != null) { - // use set here, since measurement sibling point to the same - // context roots - create(measurements.stream().map(ContextRoot::of).collect(HashSet::new, Set::addAll, Set::addAll)); + // Use set here, since measurement siblings point to the same + // context roots. Only create those ContextRoots that haven't been created yet: + create(measurements.stream().map(ContextRoot::of) + .collect(HashSet<ContextRoot>::new, Set<ContextRoot>::addAll, Set<ContextRoot>::addAll) + .stream().filter(cr -> !ODSUtils.isValidID(cr.getID())).collect(Collectors.toSet())); } executeStatements(et -> new InsertStatement(this, et), entities); - + processNtoMRelations(entities); + List<ContextRoot> roots = (List<ContextRoot>) entitiesByClassType.get(ContextRoot.class); if (roots != null) { roots.forEach(contextRoot -> { @@ -224,6 +235,7 @@ public final class ODSTransaction implements Transaction { } } executeStatements(et -> new UpdateStatement(this, et, false), entities); + processNtoMRelations(entities); } catch (AoException e) { throw new DataAccessException("Unable to update entities due to: " + e.reason, e); } catch (IOException e) { @@ -491,6 +503,55 @@ public final class ODSTransaction implements Transaction { } /** + * Processes N-to-M relations for the given entities + * @param entities + * The processed {@code Entity}s. + * @throws DataAccessException + * Thrown if the execution fails. + */ + private <T extends Entity> void processNtoMRelations(Collection<T> entities) { + for (Entity e : entities) { + context.getODSModelManager().getEntityType(e) + .getRelations() + .stream() + .filter(Relation::isNtoM) + .forEach(r -> processMtoMRelation(e, r)); + } + } + + private void processMtoMRelation(Entity entity, Relation relation) { + + List<? extends Deletable> removedRelatedEntities = ODSEntityFactory.extract(entity).getNtoMStore().getRemoved().getOrDefault(relation.getName(), Collections.emptyList()); + List<? extends Deletable> addedRelatedEntities = ODSEntityFactory.extract(entity).getNtoMStore().getAdded().getOrDefault(relation.getName(), Collections.emptyList()); + + T_LONGLONG[] removedInstIds = removedRelatedEntities.stream() + .map(Entity::getID) + .map(ODSConverter::toODSID) + .toArray(T_LONGLONG[]::new); + + T_LONGLONG[] addedInstIds = addedRelatedEntities.stream() + .map(Entity::getID) + .map(ODSConverter::toODSID) + .toArray(T_LONGLONG[]::new); + + try { + if (removedInstIds.length > 0) { + ODSEntityType entityType = ((ODSEntityType) context.getODSModelManager().getEntityType(entity)); + ElemId elemId = new ElemId(entityType.getODSID(), ODSConverter.toODSID(entity.getID())); + context.getAoSession().getApplElemAccess().setRelInst(elemId, relation.getName(), removedInstIds, SetType.REMOVE); + } + + if (addedInstIds.length > 0) { + ODSEntityType entityType = ((ODSEntityType) context.getODSModelManager().getEntityType(entity)); + ElemId elemId = new ElemId(entityType.getODSID(), ODSConverter.toODSID(entity.getID())); + context.getAoSession().getApplElemAccess().setRelInst(elemId, relation.getName(), addedInstIds, SetType.APPEND); + } + } catch (AoException e) { + throw new DataAccessException("" + e.reason, e); // TODO + } + } + + /** * Closes the co-session of this transaction. */ private void closeSession() { diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/UpdateStatement.java b/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/UpdateStatement.java index f6fa7c8..300fcfd 100644 --- a/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/UpdateStatement.java +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/UpdateStatement.java @@ -1,16 +1,16 @@ -/********************************************************************************
- * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information regarding copyright ownership.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- ********************************************************************************/
+/******************************************************************************** + * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ package org.eclipse.mdm.api.odsadapter.transaction; @@ -39,6 +39,7 @@ import org.eclipse.mdm.api.base.model.FileLink; import org.eclipse.mdm.api.base.model.FilesAttachable; import org.eclipse.mdm.api.base.model.Value; import org.eclipse.mdm.api.base.query.DataAccessException; +import org.eclipse.mdm.api.dflt.model.Role; import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig; import org.eclipse.mdm.api.odsadapter.query.ODSEntityFactory; import org.eclipse.mdm.api.odsadapter.utils.ODSConverter; @@ -126,6 +127,10 @@ final class UpdateStatement extends BaseStatement { // skip "empty" informative relation sequence continue; } + if (entry.getKey().equalsIgnoreCase(Role.ATTR_SUPERUSER_FLAG)) { + // skip superuser flag as it cannot be written through the ODS API + continue; + } Attribute attribute = getEntityType().getAttribute(entry.getKey()); diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/WriteRequestHandler.java b/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/WriteRequestHandler.java index 34c8d2c..86610a9 100644 --- a/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/WriteRequestHandler.java +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/WriteRequestHandler.java @@ -1,16 +1,16 @@ -/********************************************************************************
- * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information regarding copyright ownership.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- ********************************************************************************/
+/******************************************************************************** + * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ package org.eclipse.mdm.api.odsadapter.transaction; @@ -127,7 +127,7 @@ public final class WriteRequestHandler { Map<String, Value> values = core.getValues(); values.get(Entity.ATTR_NAME).set(writeRequest.getChannel().getName()); values.get(Entity.ATTR_MIMETYPE).set("application/x-asam.aolocalcolumn"); - values.get(AE_LC_ATTR_INDEPENDENT).set(ODSConverter.toODSValidFlag(writeRequest.isIndependent())); + values.get(AE_LC_ATTR_INDEPENDENT).set((short) (writeRequest.isIndependent() ? 1 : 0)); values.get(AE_LC_ATTR_RAWDATATYPE).set(writeRequest.getRawScalarType()); values.get(AE_LC_ATTR_REPRESENTATION).set(writeRequest.getSequenceRepresentation()); values.get(AE_LC_ATTR_AXISTYPE).set(writeRequest.getAxisType()); @@ -138,10 +138,13 @@ public final class WriteRequestHandler { String unitName = writeRequest.getChannel().getUnit().getName(); values.put(AE_LC_ATTR_VALUES, valueType.create(AE_LC_ATTR_VALUES, unitName, true, writeRequest.getValues())); - + + // OpenATFX issue: For "implicit" columns, if no value for the GenerationParameters attribute is present, + // it is attempted to transfer the local column values (through which the generation parameters are + // available in these cases) to the GenerationParameters attribute without converting them to the + // correct DS_DOUBLE data type first (unless it is a DOUBLE or LONG column), resulting in an exception. + // Hence, supply correctly converted generation parameters as a workaround: if (writeRequest.getSequenceRepresentation().isImplicit()) { - // PEAK ODS server: expects values written as generation - // parameters Object genParamValues = writeRequest.getValues(); double[] genParamD = new double[Array.getLength(genParamValues)]; IntStream.range(0, genParamD.length) @@ -152,11 +155,6 @@ public final class WriteRequestHandler { // flags if (writeRequest.areAllValid()) { values.get(AE_LC_ATTR_GLOBAL_FLAG).set((short) 15); - // PEAK ODS server issue: though global flag is true a flags - // array is expected - short[] flags = new short[Array.getLength(writeRequest.getValues())]; - Arrays.fill(flags, (short) 15); - values.get(AE_LC_ATTR_FLAGS).set(flags); } else { short[] flags = ODSConverter.toODSValidFlagSeq(writeRequest.getFlags()); values.get(AE_LC_ATTR_FLAGS).set(flags); diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverter.java b/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverter.java index ae893ca..f0d146b 100644 --- a/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverter.java +++ b/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverter.java @@ -1,16 +1,16 @@ -/********************************************************************************
- * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information regarding copyright ownership.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- ********************************************************************************/
+/******************************************************************************** + * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ package org.eclipse.mdm.api.odsadapter.utils; @@ -22,6 +22,7 @@ import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -50,6 +51,7 @@ import org.eclipse.mdm.api.base.model.Value; import org.eclipse.mdm.api.base.model.ValueType; import org.eclipse.mdm.api.base.query.Aggregation; import org.eclipse.mdm.api.base.query.DataAccessException; +import org.eclipse.mdm.api.odsadapter.ReadRequestHandler; import org.eclipse.mdm.api.odsadapter.query.ODSAttribute; import com.google.common.collect.Sets; @@ -334,15 +336,26 @@ public final class ODSConverter { && attribute.getValueType().isEnumerationType() && Sets.immutableEnumSet(Aggregation.MINIMUM, Aggregation.MAXIMUM, Aggregation.DISTINCT) .contains(aggregation)) { - return valueType.create(String.format("%s(%s)", aggregation.name(), attribute.getName()), unit, valid, + return valueType.create(getColumnName(attribute, aggregation), unit, valid, input, attribute.getEnumObj().getName()); } else { - return valueType.create(String.format("%s(%s)", aggregation.name(), attribute.getName()), unit, valid, + return valueType.create(getColumnName(attribute, aggregation), unit, valid, input); } } } + /** + * Returns the name of the attribute with its applied aggregation as returned by the ODS Server, + * for example: MAXIMUM(sortIndex) + * @param attribute + * @param aggregation + * @return the name of the attribute with the applied aggragation + */ + public static String getColumnName(Attribute attribute, Aggregation aggregation) { + return String.format("%s(%s)", aggregation.name(), attribute.getName()); + } + private static String[] toString(int[] odsValues) { return IntStream.of(odsValues).mapToObj(Integer::toString).toArray(String[]::new); } @@ -652,12 +665,18 @@ public final class ODSConverter { * @throws DataAccessException * Thrown on conversion errors. */ - public static List<MeasuredValues> fromODSMeasuredValuesSeq(NameValueSeqUnit[] odsMeasuredValuesSeq) + public static List<MeasuredValues> fromODSMeasuredValuesSeq(NameValueSeqUnit[] odsMeasuredValuesSeq, ReadRequestHandler.ColumnAttributes[] columnAttributesArray) throws DataAccessException { List<MeasuredValues> measuredValues = new ArrayList<>(odsMeasuredValuesSeq.length); + + Map<String, ReadRequestHandler.ColumnAttributes> mapColumnAttributes = new HashMap<>(); + if (null != columnAttributesArray) + { + Arrays.stream(columnAttributesArray).forEach(ca -> mapColumnAttributes.put(ca.getName(), ca)); + } for (NameValueSeqUnit odsMeasuredValues : odsMeasuredValuesSeq) { - measuredValues.add(fromODSMeasuredValues(odsMeasuredValues)); + measuredValues.add(fromODSMeasuredValues(odsMeasuredValues, mapColumnAttributes.get(odsMeasuredValues.valName))); } return measuredValues; @@ -672,7 +691,7 @@ public final class ODSConverter { * @throws DataAccessException * Thrown on conversion errors. */ - private static MeasuredValues fromODSMeasuredValues(NameValueSeqUnit odsMeasuredValues) throws DataAccessException { + private static MeasuredValues fromODSMeasuredValues(NameValueSeqUnit odsMeasuredValues, ReadRequestHandler.ColumnAttributes columnAttributes) throws DataAccessException { TS_ValueSeq odsValueSeq = odsMeasuredValues.value; DataType dataType = odsValueSeq.u.discriminator(); ScalarType scalarType; @@ -721,8 +740,19 @@ public final class ODSConverter { throw new DataAccessException( "Conversion for ODS measured points of type '" + dataType.toString() + "' does not exist."); } + + if (null == columnAttributes) + { + columnAttributes = new ReadRequestHandler.ColumnAttributes("", null, new double[0], false, null); + } - return scalarType.createMeasuredValues(odsMeasuredValues.valName, odsMeasuredValues.unit, values, + return scalarType.createMeasuredValues(odsMeasuredValues.valName, + odsMeasuredValues.unit, + columnAttributes.getSequenceRepresentation(), + columnAttributes.getGenerationParameters(), + columnAttributes.isIndependentColumn(), + columnAttributes.getAxisType(), + values, fromODSValidFlagSeq(odsValueSeq.flag)); } diff --git a/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java b/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java new file mode 100644 index 0000000..88a2f31 --- /dev/null +++ b/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java @@ -0,0 +1,209 @@ +/******************************************************************************** + * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ + + +package org.eclipse.mdm.api.odsadapter; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_NAMESERVICE; +import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_PASSWORD; +import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_SERVICENAME; +import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_USER; + +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.mdm.api.base.ConnectionException; +import org.eclipse.mdm.api.base.ServiceNotProvidedException; +import org.eclipse.mdm.api.base.Transaction; +import org.eclipse.mdm.api.base.model.User; +import org.eclipse.mdm.api.dflt.ApplicationContext; +import org.eclipse.mdm.api.dflt.EntityManager; +import org.eclipse.mdm.api.dflt.model.EntityFactory; +import org.eclipse.mdm.api.dflt.model.Role; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +//@Ignore +// FIXME 10.7.2017: this test needs a running ODS Server, that is not suitable for continous build in Jenkins. +// Comment this in for local tests only. +public class ODSRoleTest { + + /* + * ATTENTION: ========== + * + * To run this test make sure the target service is running a MDM default + * model and any database constraint which enforces a relation of Test to a + * parent entity is deactivated! + */ + + private static final Logger LOGGER = LoggerFactory.getLogger(ODSRoleTest.class); + + private static final String NAME_SERVICE = "corbaloc::1.2@%s:%s/NameService"; + + private static final String USER = "sa"; + private static final String PASSWORD = "sa"; + + private static ApplicationContext context; + private static EntityManager em; + private static EntityFactory entityFactory; + + @BeforeClass + public static void setUpBeforeClass() throws ConnectionException { + String nameServiceHost = System.getProperty("host"); + String nameServicePort = System.getProperty("port"); + String serviceName = System.getProperty("service"); + + if (nameServiceHost == null || nameServiceHost.isEmpty()) { + throw new IllegalArgumentException("name service host is unknown: define system property 'host'"); + } + + nameServicePort = nameServicePort == null || nameServicePort.isEmpty() ? String.valueOf(2809) : nameServicePort; + if (nameServicePort == null || nameServicePort.isEmpty()) { + throw new IllegalArgumentException("name service port is unknown: define system property 'port'"); + } + + if (serviceName == null || serviceName.isEmpty()) { + throw new IllegalArgumentException("service name is unknown: define system property 'service'"); + } + + Map<String, String> connectionParameters = new HashMap<>(); + connectionParameters.put(PARAM_NAMESERVICE, String.format(NAME_SERVICE, nameServiceHost, nameServicePort)); + connectionParameters.put(PARAM_SERVICENAME, serviceName + ".ASAM-ODS"); + connectionParameters.put(PARAM_USER, USER); + connectionParameters.put(PARAM_PASSWORD, PASSWORD); + + context = new ODSContextFactory().connect(connectionParameters); + em = context.getEntityManager() + .orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class)); + entityFactory = context.getEntityFactory() + .orElseThrow(() -> new IllegalStateException("Entity manager factory not available.")); + } + + @AfterClass + public static void tearDownAfterClass() throws ConnectionException { + if (context != null) { + context.close(); + } + } + + @org.junit.Test + public void testLoadRelatedUsers() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + User user = em.loadAll(User.class, "sa").get(0); + List<Role> role = em.loadRelatedEntities(user, "users2groups", Role.class); + + assertThat(role).hasSize(1).extracting(Role::getName).containsExactly("MDMSystemAdministrator"); + } + + @org.junit.Test + public void testLoadRelatedRoles() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Role role = em.loadAll(Role.class, "MDMSystemAdministrator").get(0); + List<User> user = em.loadRelatedEntities(role, "groups2users", User.class); + + assertThat(user).hasSize(1).extracting(User::getName).containsExactly("sa"); + } + + @org.junit.Test + public void testCreateUserAndRole() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + String userName = "CreateUserAndRole"; + String roleName = "CreateUserAndRole"; + + try { + Transaction transaction = em.startTransaction(); + User user = entityFactory.createUser(userName, "Test", "User"); + Role role = entityFactory.createRole(roleName); + role.addUser(user); + + transaction.create(Arrays.asList(user, role)); + transaction.commit(); + + assertThat(em.loadRelatedEntities(role, "users2groups", User.class)) + .hasSize(1) + .extracting(User::getName) + .contains(userName); + + assertThat(em.loadRelatedEntities(user, "groups2users", Role.class)) + .hasSize(1) + .extracting(Role::getName) + .contains(roleName); + } finally { + Transaction transaction = em.startTransaction(); + List<User> users = em.loadAll(User.class, userName); + transaction.delete(users); + List<Role> roles = em.loadAll(Role.class, roleName); + transaction.delete(roles); + transaction.commit(); + } + } + + @org.junit.Test + public void testAddMultipleUsersToNewRole() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + String roleName = "AddMultipleUsersToNewRole"; + try { + Transaction transaction = em.startTransaction(); + List<User> users = em.loadAll(User.class); + Role role = entityFactory.createRole(roleName); + + users.forEach(u -> role.addUser(u)); + transaction.create(Arrays.asList(role)); + transaction.commit(); + + assertThat(em.loadRelatedEntities(role, "users2groups", User.class)) + .hasSize(users.size()); + } finally { + Transaction transaction = em.startTransaction(); + List<Role> roles = em.loadAll(Role.class, roleName); + transaction.delete(roles); + transaction.commit(); + } + } + + @org.junit.Test + public void testRemoveUserFromRole() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + String userName = "RemoveUserFromRole"; + try { + Transaction transaction = em.startTransaction(); + Role role = em.load(Role.class, "1"); + User user = entityFactory.createUser(userName, "User", "User"); + + role.addUser(user); + + transaction.create(Arrays.asList(user)); + transaction.update(Arrays.asList(role)); + transaction.commit(); + + assertThat(em.loadRelatedEntities(role, "groups2users", User.class)) + .hasSize(2); + + Role role2 = em.load(Role.class, "1"); + transaction = em.startTransaction(); + role2.removeUser(user); + transaction.update(Arrays.asList(role2)); + transaction.commit(); + + assertThat(em.loadRelatedEntities(role2, "groups2users", User.class)) + .hasSize(1); + } finally { + Transaction transaction = em.startTransaction(); + List<User> users = em.loadAll(User.class, userName); + transaction.delete(users); + transaction.commit(); + } + } +} |