| /******************************************************************************** |
| * 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.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; |
| } |
| |
| /** |
| * 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) { |
| 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); |
| |
| // 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); |
| } |
| |
| } |