blob: d18d7601400d0c1e0c3b9a435e1432725f6b81e8 [file] [log] [blame]
/********************************************************************************
* Copyright (c) 2015-2020 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.dflt.model;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import org.eclipse.mdm.api.base.adapter.Core;
import org.eclipse.mdm.api.base.model.BaseEntity;
import org.eclipse.mdm.api.base.model.BaseEntityFactory;
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.Enumeration;
import org.eclipse.mdm.api.base.model.Measurement;
import org.eclipse.mdm.api.base.model.Quantity;
import org.eclipse.mdm.api.base.model.ScalarType;
import org.eclipse.mdm.api.base.model.Test;
import org.eclipse.mdm.api.base.model.TestStep;
import org.eclipse.mdm.api.base.model.Value;
import org.eclipse.mdm.api.base.model.ValueType;
import org.eclipse.mdm.api.base.model.VersionState;
/**
* Creates new entities of the default application model.
*
* @since 1.0.0
* @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
*/
public abstract class EntityFactory extends BaseEntityFactory {
// ======================================================================
// Public methods
// ======================================================================
/**
* Creates a new {@link Role}.
*
* @param name Name of the created {@code Role}.
* @return The created {@code Role} is returned.
*/
public Role createRole(String name) {
Role role = new Role(createCore(Role.class));
// properties
role.setName(name);
return role;
}
/**
* Always throws an UnsupportedOperationException since in a default model each
* {@link Test} has a parent {@link Pool}.
*
* @throws UnsupportedOperationException Is always thrown.
*/
@Override
public Test createTest(String name) {
throw new UnsupportedOperationException("Test requires a parent Pool.");
}
/**
* Creates a new {@link Project}.
*
* @param name Name of the created {@code Project}.
* @return The created {@code Project} is returned.
*/
public Project createProject(String name) {
Project project = new Project(createCore(Project.class));
// properties
project.setName(name);
return project;
}
/**
* Creates a new {@link Pool} for given {@link Project}.
*
* @param name Name of the created {@code Pool}.
* @param project The parent {@code Project}.
* @return The created {@code Pool} is returned.
*/
public Pool createPool(String name, Project project) {
Pool pool = new Pool(createCore(Pool.class));
// relations
getCore(pool).getPermanentStore().set(project);
getCore(project).getChildrenStore().add(pool);
// properties
pool.setName(name);
return pool;
}
/**
* Creates a new {@link Test} for given {@link Pool}.
*
* @param name Name of the created {@code Test}.
* @param pool The parent {@code Pool}.
* @return The created {@code Test} is returned.
*/
public Test createTest(String name, Pool pool) {
return createTest(name, pool, (Status) null);
}
/**
* Creates a new {@link Test} for given {@link Pool} using given
* {@link TemplateTest}.
*
* @param name Name of the created {@code Test}.
* @param pool The parent {@code Pool}.
* @param templateTest The template the returned {@code Test} will be derived
* from.
* @return The created {@code Test} is returned.
*/
// TODO make a decision: status in or out!
public Test createTest(String name, Pool pool, TemplateTest templateTest) {
return createTest(name, pool, null, null, templateTest);
}
/**
* Creates a new {@link ContextRoot} for given {@link TestStep} using given
* {@link TemplateRoot}.
*
* @param testStep The parent {@code TestStep}.
* @param templateRoot The template the returned {@code ContextRoot} will be
* derived from.
* @return The created {@code ContextRoot} is returned.
*/
public ContextRoot createContextRoot(TestStep testStep, TemplateRoot templateRoot) {
ContextRoot contextRoot = createContextRoot(templateRoot);
// relations
getCore(testStep).getMutableStore().set(contextRoot, templateRoot.getContextType());
return contextRoot;
}
/**
* Creates a new {@link ContextRoot} for given {@link Measurement} using given
* {@link TemplateRoot}.
*
* @param measurement The parent {@code Measurement}.
* @param templateRoot The template the returned {@code ContextRoot} will be
* derived from.
* @return The created {@code ContextRoot} is returned.
*/
public ContextRoot createContextRoot(Measurement measurement, TemplateRoot templateRoot) {
return createContextRoot(Arrays.asList(measurement), templateRoot);
}
/**
* Creates a new {@link ContextRoot} for given {@link List} if
* {@link Measurement}s using given {@link TemplateRoot}. If List is null or
* empty context root is created with no relations.
*
* @param measurements The parent {@code Measurement}.
* @param templateRoot The template the returned {@code ContextRoot} will be
* derived from.
* @return The created {@code ContextRoot} is returned.
*/
public ContextRoot createContextRoot(List<Measurement> measurements, TemplateRoot templateRoot) {
ContextRoot contextRoot = createContextRoot(templateRoot);
// relations
if (measurements != null && !measurements.isEmpty()) {
measurements.forEach(m -> getCore(m).getMutableStore().set(contextRoot, templateRoot.getContextType()));
}
return contextRoot;
}
/**
* Creates a new {@link ContextRoot} using given {@link TemplateRoot}.
*
* @param templateRoot The template the returned {@code ContextRoot} will be
* derived from.
* @return The created {@code ContextRoot} is returned.
*/
public ContextRoot createContextRoot(TemplateRoot templateRoot) {
ContextRoot contextRoot = createContextRoot(templateRoot.getName(), templateRoot.getContextType());
// relations
getCore(contextRoot).getMutableStore().set(templateRoot);
// create default active and mandatory context components
templateRoot.getTemplateComponents().stream()
.filter(TemplateComponent.IS_DEFAULT_ACTIVE.or(TemplateComponent.IS_MANDATORY))
.forEach(templateComponent -> {
createContextComponent(templateComponent.getName(), contextRoot);
});
return contextRoot;
}
/**
* @throws IllegalArgumentException Thrown if given name is already in use or
* {@link TemplateComponent} with given name
* does not exist.
*/
@Override
public ContextComponent createContextComponent(String name, ContextRoot contextRoot) {
if (contextRoot.getContextComponent(name).isPresent()) {
throw new IllegalArgumentException("Context component with name '" + name + "' already exists.");
}
TemplateRoot templateRoot = TemplateRoot.of(contextRoot)
.orElseThrow(() -> new IllegalArgumentException("Template root is not available."));
Optional<TemplateComponent> templateComponent = templateRoot.getTemplateComponent(name);
if (templateComponent.isPresent()) {
// recursively create missing parent context components
templateComponent.get().getParentTemplateComponent()
.filter(tc -> !contextRoot.getContextComponent(tc.getName()).isPresent())
.ifPresent(tc -> createContextComponent(tc.getName(), contextRoot));
// create context component if not already done
if (!contextRoot.getContextComponent(name).isPresent()) {
ContextComponent contextComponent = super.createContextComponent(
templateComponent.get().getCatalogComponent().getName(), contextRoot);
// relations
getCore(contextComponent).getMutableStore().set(templateComponent.get());
// properties
contextComponent.setName(name);
contextComponent
.setMimeType(contextComponent.getMimeType().addSubType(templateComponent.get().getName()));
hideValues(getCore(contextComponent), templateComponent.get().getTemplateAttributes());
templateComponent.get().getTemplateAttributes().forEach(ta -> {
contextComponent.getValue(ta.getName()).set(ta.getDefaultValue().extract());
});
// create default active and mandatory child context components
templateComponent.get().getTemplateComponents().stream().filter(TemplateComponent.IS_IMPLICIT_CREATE)
.forEach(childTemplateComponent -> {
createContextComponent(childTemplateComponent.getName(), contextRoot);
});
// create default active and mandatory context sensors
templateComponent.get().getTemplateSensors().stream().filter(TemplateSensor.IS_IMPLICIT_CREATE)
.forEach(templateSensor -> {
createContextSensor(templateSensor.getName(), contextComponent);
});
return contextComponent;
}
}
throw new IllegalArgumentException("Template component with name '" + name + "' does not exist.");
}
/**
* {@inheritDoc}
*/
@Override
public ContextSensor createContextSensor(String name, ContextComponent contextComponent) {
if (contextComponent.getContextSensor(name).isPresent()) {
throw new IllegalArgumentException("Context sensor with name '" + name + "' already exists.");
}
TemplateComponent templateComponent = TemplateComponent.of(contextComponent)
.orElseThrow(() -> new IllegalArgumentException("Template component is not available."));
Optional<TemplateSensor> templateSensor = templateComponent.getTemplateSensor(name);
if (templateSensor.isPresent()) {
ContextSensor contextSensor = super.createContextSensor(templateSensor.get().getCatalogSensor().getName(),
contextComponent);
// relations
getCore(contextSensor).getMutableStore().set(templateSensor.get());
// properties
contextSensor.setName(name);
hideValues(getCore(contextSensor), templateSensor.get().getTemplateAttributes());
templateSensor.get().getTemplateAttributes().forEach(ta -> {
contextSensor.getValue(ta.getName()).set(ta.getDefaultValue().extract());
});
return contextSensor;
}
throw new IllegalArgumentException("Template sensor with name '" + name + "' does not exist.");
}
/**
* Creates a new {@link CatalogComponent} with given {@link ContextType} and
* name.
*
* @param contextType The {@code ContextType}.
* @param name Name of the created {@code CatalogComponent}.
* @return The created {@code CatalogComponent} is returned.
* @throws IllegalArgumentException Thrown if name is not allowed.
*/
public CatalogComponent createCatalogComponent(ContextType contextType, String name) {
validateCatalogName(name, false);
CatalogComponent catalogComponent = new CatalogComponent(createCore(CatalogComponent.class, contextType));
// properties
catalogComponent.setName(name);
catalogComponent.setDateCreated(LocalDateTime.now());
catalogComponent.getValue("ValidFlag").set(VersionState.VALID);
return catalogComponent;
}
/**
* Creates a new {@link CatalogAttribute} for given {@link CatalogComponent}.
* The {@link ValueType} may be one of the following:
*
* <ul>
* <li>{@link ValueType#STRING}</li>
* <li>{@link ValueType#STRING_SEQUENCE}</li>
* <li>{@link ValueType#DATE}</li>
* <li>{@link ValueType#DATE_SEQUENCE}</li>
* <li>{@link ValueType#BOOLEAN}</li>
* <li>{@link ValueType#BOOLEAN_SEQUENCE}</li>
* <li>{@link ValueType#BYTE}</li>
* <li>{@link ValueType#BYTE_SEQUENCE}</li>
* <li>{@link ValueType#SHORT}</li>
* <li>{@link ValueType#SHORT_SEQUENCE}</li>
* <li>{@link ValueType#INTEGER}</li>
* <li>{@link ValueType#INTEGER_SEQUENCE}</li>
* <li>{@link ValueType#LONG}</li>
* <li>{@link ValueType#LONG_SEQUENCE}</li>
* <li>{@link ValueType#FLOAT}</li>
* <li>{@link ValueType#FLOAT_SEQUENCE}</li>
* <li>{@link ValueType#DOUBLE}</li>
* <li>{@link ValueType#DOUBLE_SEQUENCE}</li>
* <li>{@link ValueType#BYTE_STREAM}</li>
* <li>{@link ValueType#BYTE_STREAM_SEQUENCE}</li>
* <li>{@link ValueType#FLOAT_COMPLEX}</li>
* <li>{@link ValueType#FLOAT_COMPLEX_SEQUENCE}</li>
* <li>{@link ValueType#DOUBLE_COMPLEX}</li>
* <li>{@link ValueType#DOUBLE_COMPLEX_SEQUENCE}</li>
* <li>{@link ValueType#FILE_LINK}</li>
* <li>{@link ValueType#FILE_LINK_SEQUENCE}</li>
* </ul>
*
*
* @param name Name of the created {@code CatalogAttribute}.
* @param valueType The {@code ValueType}.
* @param catalogComponent The parent {@code CatalogComponent}.
* @return The created {@code CatalogAttribute} is returned.
* @throws IllegalArgumentException Thrown if given name is already in use or
* not allowed or given {@code ValueType} is
* not supported.
*/
public CatalogAttribute createCatalogAttribute(String name, ValueType<?> valueType,
CatalogComponent catalogComponent) {
validateCatalogName(name, true);
if (catalogComponent.getCatalogAttribute(name).isPresent()) {
throw new IllegalArgumentException("Catalog attribute with name '" + name + "' already exists.");
} else if (valueType.isEnumerationType() || valueType.isByteStreamType() || valueType.isUnknown()
|| valueType.isBlob()) {
throw new IllegalArgumentException("Value type '" + valueType + "' is not allowed.");
}
CatalogAttribute catalogAttribute = new CatalogAttribute(
createCore(CatalogAttribute.class, catalogComponent.getContextType()));
// relations
getCore(catalogAttribute).getPermanentStore().set(catalogComponent);
getCore(catalogComponent).getChildrenStore().add(catalogAttribute);
// properties
catalogAttribute.setName(name);
catalogAttribute.setValueType(valueType);
catalogAttribute.setSortIndex(nextIndex(catalogComponent.getCatalogAttributes()));
return catalogAttribute;
}
/**
* Creates a new {@link CatalogAttribute} for given {@link CatalogComponent}.
*
* @param name Name of the created {@code CatalogAttribute}.
* @param enumerationObject The enumeration.
* @param catalogComponent The parent {@code CatalogComponent}.
* @return The created {@code CatalogAttribute} is returned.
* @throws IllegalArgumentException Thrown if given name is already in use or
* not allowed or given enumeration class is
* not supported.
*/
public CatalogAttribute createCatalogAttribute(String name, Enumeration<?> enumerationObj,
CatalogComponent catalogComponent) {
validateCatalogName(name, true);
validateEnum(enumerationObj);
if (catalogComponent.getCatalogAttribute(name).isPresent()) {
throw new IllegalArgumentException("Catalog attribute with name '" + name + "' already exists.");
}
CatalogAttribute catalogAttribute = new CatalogAttribute(
createCore(CatalogAttribute.class, catalogComponent.getContextType()));
// relations
getCore(catalogAttribute).getPermanentStore().set(catalogComponent);
getCore(catalogComponent).getChildrenStore().add(catalogAttribute);
// properties
catalogAttribute.setName(name);
catalogAttribute.setEnumerationObj(enumerationObj);
catalogAttribute.setSortIndex(nextIndex(catalogComponent.getCatalogAttributes()));
return catalogAttribute;
}
/**
* Creates a new {@link CatalogAttribute} for given {@link CatalogSensor}. The
* {@link ValueType} may be one of the following like in
* {@link #createCatalogAttribute(String, ValueType, CatalogComponent)}:
*
* @param name Name of the created {@code CatalogAttribute}.
* @param valueType The {@code ValueType}.
* @param catalogSensor The parent {@code CatalogSensor}.
* @return The created {@code CatalogAttribute} is returned.
* @throws IllegalArgumentException Thrown if given name is already in use or
* not allowed or given {@code ValueType} is
* not supported.
*/
public CatalogAttribute createCatalogSensorAttribute(String name, ValueType<?> valueType,
CatalogSensor catalogSensor) {
validateCatalogName(name, true);
if (catalogSensor.getCatalogAttribute(name).isPresent()) {
throw new IllegalArgumentException("CatalogSensor attribute with name '" + name + "' already exists.");
} else if (valueType.isEnumerationType() || valueType.isByteStreamType() || valueType.isUnknown()
|| valueType.isBlob()) {
throw new IllegalArgumentException("Value type '" + valueType + "' is not allowed.");
}
CatalogAttribute catalogAttribute = new CatalogAttribute(createCore(CatalogAttribute.class));
// relations
getCore(catalogAttribute).getPermanentStore().set(catalogSensor);
getCore(catalogSensor).getChildrenStore().add(catalogAttribute);
// properties
catalogAttribute.setName(name);
catalogAttribute.setValueType(valueType);
catalogAttribute.setSortIndex(nextIndex(catalogSensor.getCatalogAttributes()));
return catalogAttribute;
}
/**
* Creates a new {@link CatalogSensor} for given {@link CatalogComponent}.
*
* @param name Name of the created {@code CatalogSensor}.
* @param enumerationObject The enumeration.
* @param catalogComponent The parent {@code CatalogComponent}.
* @return The created {@code CatalogSensor} is returned.
* @throws IllegalArgumentException Thrown if given name is already in use or
* not allowed
*/
public CatalogSensor createCatalogSensor(String name, CatalogComponent catalogComponent) {
validateCatalogName(name, false);
if (!catalogComponent.getContextType().isTestEquipment()) {
throw new IllegalArgumentException("Catalog component is not of type 'TESTEQUIPMENT'");
} else if (catalogComponent.getCatalogSensor(name).isPresent()) {
throw new IllegalArgumentException("Catalog sensor with name '" + name + "' already exists.");
}
CatalogSensor catalogSensor = new CatalogSensor(createCore(CatalogSensor.class));
// relations
getPermanentStore(catalogSensor).set(catalogComponent);
getChildrenStore(catalogComponent).add(catalogSensor);
// properties
catalogSensor.setName(name);
catalogSensor.setDateCreated(LocalDateTime.now());
return catalogSensor;
}
/**
* Creates a new {@link TemplateRoot} with given {@link ContextType} and name.
*
* @param contextType The {@code ContextType}.
* @param name Name of the created {@code TemplateRoot}.
* @return The created {@code TemplateRoot} is returned.
*/
public TemplateRoot createTemplateRoot(ContextType contextType, String name) {
TemplateRoot templateRoot = new TemplateRoot(createCore(TemplateRoot.class, contextType));
// properties
templateRoot.setName(name);
templateRoot.setDateCreated(LocalDateTime.now());
templateRoot.setVersionState(VersionState.EDITABLE);
templateRoot.setVersion(Integer.valueOf(1));
return templateRoot;
}
/**
* Creates a new {@link TemplateComponent} for given {@link TemplateRoot} using
* given {@link CatalogComponent}.
*
* @param name Name of the created {@code TemplateComponent}.
* @param templateRoot The parent {@code TemplateRoot}.
* @param catalogComponent The associated {@link CatalogComponent}.
* @return The created {@code TemplateComponent} is returned.
* @throws IllegalArgumentException Thrown if {@code ContextType} of {@code
* TemplateRoot} and {@code CatalogComponent} do not match or
* given name is already in use.
*/
public TemplateComponent createTemplateComponent(String name, TemplateRoot templateRoot,
CatalogComponent catalogComponent) {
if (!templateRoot.getContextType().equals(catalogComponent.getContextType())) {
throw new IllegalArgumentException("Context type of template root and catalog component do not match.");
} else if (templateRoot.getTemplateComponent(name).isPresent()) {
throw new IllegalArgumentException("Template component with name '" + name + "' already exists.");
}
TemplateComponent templateComponent = new TemplateComponent(
createCore(TemplateComponent.class, templateRoot.getContextType()));
// relations
getCore(templateComponent).getPermanentStore().set(templateRoot);
getCore(templateComponent).getMutableStore().set(catalogComponent);
getCore(templateRoot).getChildrenStore().add(templateComponent);
// properties
templateComponent.setName(name);
templateComponent.setOptional(Boolean.TRUE);
templateComponent.setDefaultActive(Boolean.TRUE);
templateComponent.setSeriesConstant(Boolean.TRUE);
templateComponent.setSortIndex(nextIndex(templateRoot.getTemplateComponents()));
// create template attributes
catalogComponent.getCatalogAttributes().forEach(ca -> createTemplateAttribute(ca.getName(), templateComponent));
return templateComponent;
}
/**
* Creates a new {@link TemplateComponent} for given {@link TemplateComponent}
* using given {@link CatalogComponent}.
*
* @param name Name of the created
* {@code TemplateComponent}.
* @param partentComponentTemplate The parent {@code TemplateComponent}.
* @param catalogComponent The associated {@link CatalogComponent}.
* @return The created {@code TemplateComponent} is returned.
* @throws IllegalArgumentException Thrown if {@code ContextType} of {@code
* TemplateComponent} and {@code CatalogComponent} do not match or
* given name is already in use.
*/
public TemplateComponent createTemplateComponent(String name, TemplateComponent partentComponentTemplate,
CatalogComponent catalogComponent) {
TemplateRoot templateRoot = partentComponentTemplate.getTemplateRoot();
if (!templateRoot.getContextType().equals(catalogComponent.getContextType())) {
throw new IllegalArgumentException("Context type of template root and catalog component do not match.");
} else if (templateRoot.getTemplateComponent(name).isPresent()) {
throw new IllegalArgumentException("Template component with name '" + name + "' already exists.");
}
TemplateComponent templateComponent = new TemplateComponent(
createCore(TemplateComponent.class, templateRoot.getContextType()));
// relations
getCore(templateComponent).getPermanentStore().set(partentComponentTemplate);
getCore(templateComponent).getMutableStore().set(catalogComponent);
getCore(partentComponentTemplate).getChildrenStore().add(templateComponent);
// properties
templateComponent.setName(name);
templateComponent.setOptional(Boolean.TRUE);
templateComponent.setDefaultActive(Boolean.TRUE);
templateComponent.setSeriesConstant(Boolean.TRUE);
templateComponent.setSortIndex(nextIndex(partentComponentTemplate.getTemplateComponents()));
// create template attributes
catalogComponent.getCatalogAttributes().forEach(ca -> createTemplateAttribute(ca.getName(), templateComponent));
return templateComponent;
}
/**
* Creates a new {@link TemplateAttribute} for given {@link TemplateComponent}.
*
* @param name Name of the created {@code TemplateAttribute}.
* @param templateComponent The parent {@code TemplateComponent}.
* @return The created {@code TemplateAttribute} is returned.
* @throws IllegalArgumentException Thrown if given name is already in use.
*/
public TemplateAttribute createTemplateAttribute(String name, TemplateComponent templateComponent) {
if (templateComponent.getTemplateAttribute(name).isPresent()) {
throw new IllegalArgumentException("Template attribute with name '" + name + "' already exists.");
}
CatalogComponent catalogComponent = templateComponent.getCatalogComponent();
Optional<CatalogAttribute> catalogAttribute = catalogComponent.getCatalogAttribute(name);
if (catalogAttribute.isPresent()) {
TemplateAttribute templateAttribute = new TemplateAttribute(
createCore(TemplateAttribute.class, catalogComponent.getContextType()));
// relations
getCore(templateAttribute).getPermanentStore().set(templateComponent);
getCore(templateAttribute).getMutableStore().set(catalogAttribute.get());
getCore(templateComponent).getChildrenStore().add(templateAttribute);
// properties
templateAttribute.setName(name);
templateAttribute.setValueReadOnly(Boolean.FALSE);
templateAttribute.setOptional(Boolean.TRUE);
return templateAttribute;
}
throw new IllegalArgumentException("Catalog attribute with name '" + name + "' does not exists.");
}
/**
* Creates a new {@link TemplateSensor} for given {@link TemplateComponent}
* based on the given {@link CatalogSensor}.
*
* @param name Name of the created {@code TemplateAttribute}.
* @param templateComponent The parent {@code TemplateComponent}.
* @param catalogSensor reference CatalogSensor
* @param quantity Quantity to create {@link TemplateSensor} for
* @return The created {@code TemplateSensor} is returned.
* @throws IllegalArgumentException Thrown if given name is already in use.
*/
public TemplateSensor createTemplateSensor(String name, TemplateComponent templateComponent,
CatalogSensor catalogSensor, Quantity quantity) {
if (templateComponent.getTemplateSensor(name).isPresent()) {
throw new IllegalArgumentException("Template sensor with name '" + name + "' already exists.");
}
if (catalogSensor != null) {
TemplateSensor templateSensor = new TemplateSensor(createCore(TemplateSensor.class));
// create all implicit TemplateAttributes
for (CatalogAttribute catAttr : catalogSensor.getCatalogAttributes()) {
TemplateAttribute tplAttr = new TemplateAttribute(createCore(TemplateAttribute.class));
tplAttr.setName(catAttr.getName());
tplAttr.setValueReadOnly(Boolean.FALSE);
tplAttr.setOptional(Boolean.TRUE);
getPermanentStore(tplAttr).set(templateSensor);
getMutableStore(tplAttr).set(catAttr);
getCore(templateSensor).getChildrenStore().add(tplAttr);
}
// relations
getPermanentStore(templateSensor).set(templateComponent);
getMutableStore(templateSensor).set(catalogSensor);
getMutableStore(templateSensor).set(quantity);
getChildrenStore(templateComponent).add(templateSensor);
// properties
templateSensor.setName(name);
templateSensor.setDefaultActive(true);
templateSensor.setOptional(Boolean.TRUE);
return templateSensor;
}
throw new IllegalArgumentException("Catalog attribute with name '" + name + "' does not exists.");
}
/**
* Creates a new {@link TemplateTestStep}.
*
* @param name Name of the created {@code TemplateTestStep}.
* @return The created {@code TemplateTestStep} is returned.
*/
public TemplateTestStep createTemplateTestStep(String name) {
TemplateTestStep templateTestStep = new TemplateTestStep(createCore(TemplateTestStep.class));
// properties
templateTestStep.setName(name);
templateTestStep.setDateCreated(LocalDateTime.now());
templateTestStep.setVersionState(VersionState.EDITABLE);
templateTestStep.setVersion(Integer.valueOf(1));
return templateTestStep;
}
/**
* Creates a new {@link TemplateTest}.
*
* @param name Name of the created {@code TemplateTest}.
* @return The created {@code TemplateTest} is returned.
*/
public TemplateTest createTemplateTest(String name) {
TemplateTest templateTest = new TemplateTest(createCore(TemplateTest.class));
// properties
templateTest.setName(name);
templateTest.setDateCreated(LocalDateTime.now());
templateTest.setVersion(Integer.valueOf(1));
templateTest.setVersionState(VersionState.EDITABLE);
return templateTest;
}
/**
* Creates a new {@link TemplateTestStepUsage} for given {@link TemplateTest}
* using given {@link TemplateTestStep}.
*
* @param name Name of the created {@code TemplateTestStepUsage}.
* @param templateTest The parent {@link TemplateTest}.
* @param templateTestStep The related {@link TemplateTestStep}.
* @return The created {@code TemplateTestStepUsage} is returned.
*/
public TemplateTestStepUsage createTemplateTestStepUsage(String name, TemplateTest templateTest,
TemplateTestStep templateTestStep) {
if (templateTest.getTemplateTestStepUsage(name).isPresent()) {
throw new IllegalArgumentException("Template test step usage with name '" + name + "' already exists.");
}
TemplateTestStepUsage templateTestStepUsage = new TemplateTestStepUsage(
createCore(TemplateTestStepUsage.class));
// relations
getCore(templateTestStepUsage).getPermanentStore().set(templateTest);
getCore(templateTestStepUsage).getMutableStore().set(templateTestStep);
getCore(templateTest).getChildrenStore().add(templateTestStepUsage);
// properties
templateTestStepUsage.setName(name);
templateTestStepUsage.setOptional(Boolean.TRUE);
templateTestStepUsage.setDefaultActive(Boolean.TRUE);
templateTestStepUsage.setSortIndex(nextIndex(templateTest.getTemplateTestStepUsages()));
return templateTestStepUsage;
}
/**
* Creates a new {@link ValueList}.
*
* @param name Name of the created {@code ValueList}.
* @return The created {@code ValueList} is returned.
*/
public ValueList createValueList(String name) {
ValueList valueList = new ValueList(createCore(ValueList.class));
// properties
valueList.setName(name);
valueList.setDateCreated(LocalDateTime.now());
return valueList;
}
/**
* Creates a new {@link ValueListValue} for given {@link ValueList}.
*
* @param name Name of the created {@code ValueListValue}.
* @param valueList The parent {@code ValueList}.
* @return The created {@code ValueListValue} is returned.
*/
public ValueListValue createValueListValue(String name, ValueList valueList) {
if (valueList.getValueListValue(name).isPresent()) {
throw new IllegalArgumentException("Value list value with name '" + name + "' already exists.");
}
ValueListValue valueListValue = new ValueListValue(createCore(ValueListValue.class));
// relations
getCore(valueListValue).getPermanentStore().set(valueList);
getCore(valueList).getChildrenStore().add(valueListValue);
// properties
valueListValue.setName(name);
valueListValue.setSortIndex(nextIndex(valueList.getValueListValues()));
// this property is hidden by the public API and is not allowed to be
// modified!
valueListValue.getValue(ValueListValue.ATTR_SCALAR_TYPE).set(ScalarType.STRING);
return valueListValue;
}
/**
* Creates a new {@link Classification} for given {@link Domain},
* {@link ProjectDomain} and {@link Status}.
*
* @param domain The {@link Domain} for the {@link Classification}
* @param projectDomain The {@link ProjectDomain} for the {@link Classification}
* @param status The {@link Status} for the {@link Classification}
* @return The created {@link Classification} is returned.
*/
public Classification createClassification(Domain domain, ProjectDomain projectDomain, Status status) {
String name = String.format("ProjDomainId_%s.DomainId_%s.StatusId_%s", projectDomain.getID(), domain.getID(),
status.getID());
return createClassification(name, status, projectDomain, domain);
}
/**
* Creates a new {@link Classification} for given {@link Domain},
* {@link ProjectDomain} and {@link Status}.
*
* @param name The name for the {@link Classification}
* @param status The {@link Status} for the {@link Classification}
* @param projectDomain The {@link ProjectDomain} for the {@link Classification}
* @param domain The {@link Domain} for the {@link Classification}
* @return The created {@link Classification} is returned.
*/
public Classification createClassification(String name, Status status, ProjectDomain projectDomain, Domain domain) {
Classification classification = new Classification(createCore(Classification.class));
getMutableStore(classification).set(status);
getMutableStore(classification).set(projectDomain);
getMutableStore(classification).set(domain);
// properties
classification.setName(name);
return classification;
}
/**
* Creates a new {@link ProjectDomain} with given name.
*
* @param name Name of the {@link ProjectDomain}
* @return The created {@link ProjectDomain} is returned.
*/
public ProjectDomain createProjectDomain(String name) {
ProjectDomain projectDomain = new ProjectDomain(createCore(ProjectDomain.class));
// properties
projectDomain.setName(name);
return projectDomain;
}
/**
* Creates a new {@link Domain} with given name.
*
* @param name Name of the {@link Domain}
* @return The created {@link Domain} is returned.
*/
public Domain createDomain(String name) {
Domain domain = new Domain(createCore(Domain.class));
// properties
domain.setName(name);
return domain;
}
// ======================================================================
// Protected methods
// ======================================================================
/**
* Creates a new {@link Test} for given {@link Pool} using given
* {@link TemplateTest}.
*
* @param name Name of the created {@code Test}.
* @param pool The parent {@code Pool}.
* @param statusTest The related {@link Status} of the created {@code
* Test} .
* @param statusTestStep The related {@link Status} of the created {@code
* TestStep} .
* @param templateTest The template the returned {@code Test} will be derived
* from.
* @return The created {@code Test} is returned.
*/
// TODO make a decision: status in or out!
protected Test createTest(String name, Pool pool, Status statusTest, Status statusTestStep,
TemplateTest templateTest) {
Test test = createTest(name, pool, statusTest);
// relations
getCore(test).getMutableStore().set(templateTest);
// create default active and mandatory test steps according to the
// template
templateTest.getTemplateTestStepUsages().stream().filter(TemplateTestStepUsage.IS_IMPLICIT_CREATE)
.map(TemplateTestStepUsage::getTemplateTestStep).forEach(templateTestStep -> {
createTestStep(test, statusTestStep, templateTestStep);
});
return test;
}
/**
* Creates a new {@link Test} for given {@link Pool} using given name,
* {@link TemplateTest} and {@link Classification}.
*
* @param name Name of the created {@code Test}.
* @param pool The parent {@code Pool}.
* @param templateTest The template the returned {@code Test} will be derived
* from.
* @param classification The {@link Classification} for the created
* {@link Test}.
* @param withTestSteps If true, {@link TestStep}s are automatically created
* based on configured {@link TemplateTestStepUsage}.
* @return The created {@code Test} is returned.
*/
public Test createTest(String name, Pool pool, TemplateTest templateTest, Classification classification,
boolean withTestSteps) {
// TODO
Test test = createTest(name, pool);
// relations
if (templateTest != null) {
getCore(test).getMutableStore().set(templateTest);
}
getCore(test).getMutableStore().set(classification);
if (withTestSteps && templateTest != null) {
// create default active and mandatory test steps according to the
// template
templateTest.getTemplateTestStepUsages().stream().filter(TemplateTestStepUsage.IS_IMPLICIT_CREATE)
.map(TemplateTestStepUsage::getTemplateTestStep).forEach(templateTestStep -> {
createTestStep(test, templateTestStep, classification);
});
}
return test;
}
/**
* Creates a new {@link TestStep} for given {@link Test} using given
* {@link TemplateTestStep} and {@link Classification}.
*
* @param test The parent {@code Test}.
* @param templateTestStep The template the returned {@code TestStep} will be
* derived from.
* @param classification The {@link Classification} for the created
* {@link TestStep}.
* @return The created {@code TestStep} is returned.
*/
public TestStep createTestStep(Test test, TemplateTestStep templateTestStep, Classification classification) {
TestStep testStep = createTestStep(test, templateTestStep);
getCore(testStep).getMutableStore().set(classification);
return testStep;
}
/**
* Creates a new {@link TestStep} for given {@link Test} using given
* {@link TemplateTestStep} and {@link Classification}.
*
* @param name Name of the created {@code TestStep}.
* @param test The parent {@code Test}.
* @param classification The {@link Classification} for the created
* {@link TestStep}.
* @return The created {@code TestStep} is returned.
*/
public TestStep createTestStep(String name, Test test, Classification classification) {
TestStep testStep = createTestStep(name, test);
getCore(testStep).getMutableStore().set(classification);
return testStep;
}
/**
* Creates a new {@link TestStep} for given {@link Test} using given name,
* {@link TemplateTestStep} and {@link Classification}.
*
* @param name Name of the created {@code TestStep}.
* @param test The parent {@code Test}.
* @param templateTestStep The template the returned {@code TestStep} will be
* derived from.
* @param classification The {@link Classification} for the created
* {@link TestStep}.
* @return The created {@code TestStep} is returned.
*/
public TestStep createTestStep(String name, Test test, TemplateTestStep templateTestStep,
Classification classification) {
TestStep testStep = createTestStep(test, templateTestStep);
getCore(testStep).getMutableStore().set(classification);
testStep.setName(name);
return testStep;
}
/**
* Create a new {@link ExtSystem}
* @param name The name of the external system
* @return
*/
public ExtSystem createExtSystem(String name) {
ExtSystem extSystem = new ExtSystem(createCore(ExtSystem.class));
extSystem.setName(name);
return extSystem;
}
/**
* Create a new {@link ExtSystemAttribute}
* @param name The name of the external system attribute
* @param extSystem The parent {@link ExtSystem}
* @return
*/
public ExtSystemAttribute createExtSystemAttribute(String name, ExtSystem extSystem) {
ExtSystemAttribute extSystemAttribute = new ExtSystemAttribute(createCore(ExtSystemAttribute.class));
getCore(extSystemAttribute).getPermanentStore().set(extSystem);
getCore(extSystem).getChildrenStore().add(extSystemAttribute);
extSystemAttribute.setName(name);
return extSystemAttribute;
}
/**
* Create a new {@link MDMAttribute}
* @param name The name of the mdm attribute
* @param extSystemAttribute The parent {@link ExtSystemAttribute}
* @return
*/
public MDMAttribute createMDMAttribute(String name, ExtSystemAttribute extSystemAttribute) {
MDMAttribute mdmAttribute = new MDMAttribute(createCore(MDMAttribute.class));
getCore(mdmAttribute).getPermanentStore().set(extSystemAttribute);
getCore(extSystemAttribute).getChildrenStore().add(mdmAttribute);
mdmAttribute.setName(name);
String[] values = name.split("\\.");
if(values.length == 3) {
mdmAttribute.setComponentType(values[0]);
mdmAttribute.setComponentName(values[1]);
mdmAttribute.setAttributeName(values[2]);
}
return mdmAttribute;
}
/**
* Creates a new {@link TestStep} for given {@link Test} using given
* {@link TemplateTestStep} and {@link Classification}. Doesn't create context
* roots
*
* @param test The parent {@code Test}.
* @param templateTestStep The template the returned {@code TestStep} will be
* derived from.
* @param classification The {@link Classification} for the created
* {@link TestStep}.
* @return The created {@code TestStep} is returned.
*/
public TestStep createTestStepWithOutContextRoots(Test test, TemplateTestStep templateTestStep,
Classification classification) {
TestStep testStep = createTestStepWithOutContextRoots(test, templateTestStep);
getCore(testStep).getMutableStore().set(classification);
return testStep;
}
/**
* Creates a new {@link TestStep} for given {@link Test} using given
* {@link TemplateTestStep}. Doesn't create context roots
*
* @param test The parent {@code Test}.
* @param templateTestStep The template the returned {@code TestStep} will be
* derived from.
* @return The created {@code TestStep} is returned.
*/
public TestStep createTestStepWithOutContextRoots(Test test, TemplateTestStep templateTestStep) {
return createTestStepWithOutContextRoots(test, null, templateTestStep);
}
/**
* Creates a new {@link TestStep} for given {@link Test} using given
* {@link TemplateTestStep}.
*
* @param test The parent {@code Test}.
* @param status The related {@link Status}.
* @param templateTestStep The template the returned {@code TestStep} will be
* derived from.
* @return The created {@code TestStep} is returned.
*/
// TODO make a decision: status in or out!
protected TestStep createTestStepWithOutContextRoots(Test test, Status status, TemplateTestStep templateTestStep) {
TemplateTest templateTest = TemplateTest.of(test)
.orElseThrow(() -> new IllegalArgumentException("Template test is not available."));
if (!templateTest.contains(templateTestStep)) {
throw new IllegalArgumentException("Template test step is not part of the test template.");
}
TestStep testStep = createTestStep(templateTestStep.getName(), test, status);
// relations
getCore(testStep).getMutableStore().set(templateTestStep);
return testStep;
}
/**
* Creates a new {@link Test} for given {@link Pool}.
*
* @param name Name of the created {@code Test}.
* @param pool The parent {@code Pool}.
* @param status The related {@link Status}.
* @return The created {@code Test} is returned.
*/
// TODO make a decision: status in or out!
protected Test createTest(String name, Pool pool, Status status) {
Test test = super.createTest(name);
// relations
getCore(test).getPermanentStore().set(pool);
getCore(pool).getChildrenStore().add(test);
return test;
}
/**
* Creates a new {@link TestStep} for given {@link Test} using given
* {@link TemplateTestStep}.
*
* @param test The parent {@code Test}.
* @param templateTestStep The template the returned {@code TestStep} will be
* derived from.
* @return The created {@code TestStep} is returned.
*/
public TestStep createTestStep(Test test, TemplateTestStep templateTestStep) {
return createTestStep(test, null, templateTestStep);
}
/**
* Creates a new {@link TestStep} for given {@link Test} using given
* {@link TemplateTestStep}.
*
* @param test The parent {@code Test}.
* @param status The related {@link Status}.
* @param templateTestStep The template the returned {@code TestStep} will be
* derived from.
* @return The created {@code TestStep} is returned.
*/
// TODO make a decision: status in or out!
protected TestStep createTestStep(Test test, Status status, TemplateTestStep templateTestStep) {
TestStep testStep = createTestStepWithOutContextRoots(test, status, templateTestStep);
// create initial context roots
templateTestStep.getTemplateRoots().forEach(templateRoot -> createContextRoot(testStep, templateRoot));
return testStep;
}
/**
* Creates a new {@link TestStep} for given {@link Test}.
*
* @param name Name of the created {@code Test}.
* @param test The parent {@code Test}.
* @param status The related {@link Status}.
* @return The created {@code TestStep} is returned.
*/
// TODO make a decision: status in or out!
protected TestStep createTestStep(String name, Test test, Status status) {
TestStep testStep = super.createTestStep(name, test);
if (status != null) {
status.assign(testStep);
}
return testStep;
}
/**
* {@inheritDoc}
*/
@Override
protected <T extends BaseEntity> T createBaseEntity(Class<T> clazz, Core core) {
try {
Constructor<T> constructor = clazz.getDeclaredConstructor(Core.class);
try {
return constructor.newInstance(core);
} catch (IllegalAccessException exc) {
return super.createBaseEntity(clazz, core);
}
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException exc) {
throw new IllegalStateException(exc.getMessage(), exc);
}
}
/**
* Checks whether given enumeration is defined in the application model or not.
*
* @param enumerationObj The checked enumeration class.
* @throws IllegalArgumentException Thrown if given enumeration class is not
* supported.
*/
protected abstract void validateEnum(Enumeration<?> enumerationObj);
// ======================================================================
// Private methods
// ======================================================================
/**
* Checks whether given catalog name is allowed or not.
*
* @param name The checked name.
* @param isAttributeName Flag indicates whether given name is for a catalog
* attribute.
* @throws IllegalArgumentException Thrown if given name is not allowed.
*/
private static void validateCatalogName(String name, boolean isAttributeName) {
if (!isValidCatalogName(name)) {
throw new IllegalArgumentException(
"A catalog name is not allowed to be empty and " + "must not exceed 30 characters.");
} else if (name.toLowerCase(Locale.ROOT).startsWith("ao")) {
throw new IllegalArgumentException("A catalog name is not allowed to " + "start with 'ao' (case ignored).");
} else if (!name.matches("^[\\w]+$")) {
throw new IllegalArgumentException(
"A calatog name may only constists of the " + "following characters: a-z, A-Z, 0-9 or _.");
} else if (isAttributeName && Arrays.asList("id", "name", "mimetype").contains(name.toLowerCase(Locale.ROOT))) {
throw new IllegalArgumentException(
"A catalog attribute name is not allowed to be " + "'id', 'name' or 'mimetype' (case ignored).");
}
}
/**
* Checks whether given catalog name is valid
*
* @param name The checked name.
* @return Returns {@code true} if name is a valid catalog name
*/
private static boolean isValidCatalogName(String name) {
return name != null && !name.isEmpty() && name.length() <= 30;
}
/**
* Hides {@link Value} containers missing in the templates.
*
* @param contextCore The {@link ContextComponent} {@link Core}.
* @param templateAttributes The {@link TemplateAttribute}s of the template.
*/
private static void hideValues(Core contextCore, List<TemplateAttribute> templateAttributes) {
Set<String> names = new HashSet<>(contextCore.getValues().keySet());
names.remove(Entity.ATTR_NAME);
names.remove(Entity.ATTR_MIMETYPE);
templateAttributes.stream().map(Entity::getName).forEach(names::remove);
contextCore.hideValues(names);
}
}