blob: 31daca156f91836274aeb079ad2b9b96538849c0 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2021 the Eclipse BaSyx Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
******************************************************************************/
package org.eclipse.basyx.aas.metamodel.map;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.basyx.aas.metamodel.api.IAssetAdministrationShell;
import org.eclipse.basyx.aas.metamodel.api.parts.IConceptDictionary;
import org.eclipse.basyx.aas.metamodel.api.parts.IView;
import org.eclipse.basyx.aas.metamodel.api.parts.asset.IAsset;
import org.eclipse.basyx.aas.metamodel.api.security.ISecurity;
import org.eclipse.basyx.aas.metamodel.exception.MetamodelConstructionException;
import org.eclipse.basyx.aas.metamodel.map.parts.Asset;
import org.eclipse.basyx.aas.metamodel.map.parts.ConceptDictionary;
import org.eclipse.basyx.aas.metamodel.map.parts.View;
import org.eclipse.basyx.aas.metamodel.map.security.Security;
import org.eclipse.basyx.submodel.metamodel.api.ISubModel;
import org.eclipse.basyx.submodel.metamodel.api.dataspecification.IEmbeddedDataSpecification;
import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier;
import org.eclipse.basyx.submodel.metamodel.api.identifier.IdentifierType;
import org.eclipse.basyx.submodel.metamodel.api.parts.IConceptDescription;
import org.eclipse.basyx.submodel.metamodel.api.qualifier.IAdministrativeInformation;
import org.eclipse.basyx.submodel.metamodel.api.reference.IReference;
import org.eclipse.basyx.submodel.metamodel.api.reference.enums.KeyElements;
import org.eclipse.basyx.submodel.metamodel.map.SubModel;
import org.eclipse.basyx.submodel.metamodel.map.modeltype.ModelType;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.AdministrativeInformation;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.HasDataSpecification;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.LangStrings;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.Referable;
import org.eclipse.basyx.submodel.metamodel.map.reference.Reference;
import org.eclipse.basyx.submodel.metamodel.map.reference.ReferenceHelper;
import org.eclipse.basyx.vab.exception.FeatureNotImplementedException;
import org.eclipse.basyx.vab.model.VABModelMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* AssetAdministrationShell class <br/>
* Does not implement IAssetAdministrationShell since there are only references
* stored in this map
*
* @author kuhn, schnicke
*
*/
public class AssetAdministrationShell extends VABModelMap<Object> implements IAssetAdministrationShell {
private static Logger logger = LoggerFactory.getLogger(AssetAdministrationShell.class);
public static final String SECURITY = "security";
public static final String DERIVEDFROM = "derivedFrom";
public static final String ASSET = "asset";
public static final String ASSETREF = "assetRef"; // Currently not standard conforming
public static final String SUBMODELS = "submodels"; // Used for storing keys to conform to the standard
public static final String VIEWS = "views";
public static final String CONCEPTDICTIONARY = "conceptDictionary";
public static final String TYPE = "type";
public static final String ADDRESS = "address";
public static final String MODELTYPE = "AssetAdministrationShell";
/**
* Constructor
*/
public AssetAdministrationShell() {
this(null, null, new Asset(), new HashSet<SubModel>(), new HashSet<IConceptDictionary>(), new HashSet<IView>());
}
/**
* Constructor accepting only mandatory attributes
* @param idShort
* @param identification
* @param asset
*/
public AssetAdministrationShell(String idShort, IIdentifier identification, Asset asset) {
this(null, null, asset, new HashSet<SubModel>(), new HashSet<IConceptDictionary>(), new HashSet<IView>());
setIdentification(identification);
setIdShort(idShort);
}
public AssetAdministrationShell(Reference derivedFrom, Security security, Asset asset,
Collection<SubModel> submodels, Collection<IConceptDictionary> dictionaries, Collection<IView> views) {
// Add model type
putAll(new ModelType(MODELTYPE));
// Add qualifiers
putAll(new Identifiable());
putAll(new HasDataSpecification());
setSubmodelReferences(new HashSet<IReference>());
// Add attributes
setSecurity(security);
setDerivedFrom(derivedFrom);
setAsset(asset);
setSubModels(submodels);
setViews(views);
setConceptDictionary(dictionaries);
}
/**
* Creates a AssetAdministrationShell object from a map
*
* @param obj
* a AssetAdministrationShell object as raw map
* @return a AssetAdministrationShell object, that behaves like a facade for the
* given map
*/
public static AssetAdministrationShell createAsFacade(Map<String, Object> map) {
if (map == null) {
return null;
}
if (!isValid(map)) {
throw new MetamodelConstructionException(AssetAdministrationShell.class, map);
}
if (!map.containsKey(SUBMODELS)) {
map.put(SUBMODELS, new ArrayList<>());
}
AssetAdministrationShell ret = new AssetAdministrationShell();
ret.setMap(map);
return ret;
}
/**
* Check whether all mandatory elements for the metamodel
* exist in a map
* @return true/false
*/
@SuppressWarnings("unchecked")
public static boolean isValid(Map<String, Object> map) {
return Identifiable.isValid(map) &&
map.containsKey(AssetAdministrationShell.ASSET) &&
Asset.isValid((Map<String, Object>)map.get(AssetAdministrationShell.ASSET));
}
@Override
public IAdministrativeInformation getAdministration() {
return Identifiable.createAsFacade(this, getKeyElement()).getAdministration();
}
@Override
public IIdentifier getIdentification() {
return Identifiable.createAsFacade(this, getKeyElement()).getIdentification();
}
public void setAdministration(AdministrativeInformation information) {
Identifiable.createAsFacade(this, getKeyElement()).setAdministration(information);
}
public void setIdentification(IIdentifier id) {
setIdentification(id.getIdType(), id.getId());
}
public void setIdentification(IdentifierType idType, String id) {
Identifiable.createAsFacadeNonStrict(this, getKeyElement()).setIdentification(idType, id);
}
@Override
public Collection<IReference> getDataSpecificationReferences() {
return HasDataSpecification.createAsFacade(this).getDataSpecificationReferences();
}
public void setDataSpecificationReferences(Collection<IReference> ref) {
HasDataSpecification.createAsFacade(this).setDataSpecificationReferences(ref);
}
@Override
public Collection<IEmbeddedDataSpecification> getEmbeddedDataSpecifications() {
return HasDataSpecification.createAsFacade(this).getEmbeddedDataSpecifications();
}
public void setEmbeddedDataSpecifications(Collection<IEmbeddedDataSpecification> embeddedDataSpecifications) {
HasDataSpecification.createAsFacade(this).setEmbeddedDataSpecifications(embeddedDataSpecifications);
}
public void setIdShort(String id) {
Referable.createAsFacadeNonStrict(this, getKeyElement()).setIdShort(id);
}
public void setSecurity(ISecurity security) {
put(AssetAdministrationShell.SECURITY, security);
}
@SuppressWarnings("unchecked")
@Override
public ISecurity getSecurity() {
return Security.createAsFacade((Map<String, Object>) get(AssetAdministrationShell.SECURITY));
}
public void setDerivedFrom(IReference derivedFrom) {
put(AssetAdministrationShell.DERIVEDFROM, derivedFrom);
}
@SuppressWarnings("unchecked")
@Override
public IReference getDerivedFrom() {
return Reference.createAsFacade((Map<String, Object>) get(AssetAdministrationShell.DERIVEDFROM));
}
public void setAsset(Asset asset) {
put(AssetAdministrationShell.ASSET, asset);
}
@SuppressWarnings("unchecked")
@Override
public IAsset getAsset() {
return Asset.createAsFacade((Map<String, Object>) get(AssetAdministrationShell.ASSET));
}
@SuppressWarnings("unchecked")
@Override
public IReference getAssetReference() {
return Reference.createAsFacade((Map<String, Object>) get(ASSETREF));
}
public void setAssetReference(Reference ref) {
put(ASSETREF, ref);
}
@SuppressWarnings("unchecked")
public void setSubModels(Collection<SubModel> submodels) {
setSubmodelParent(submodels);
// Clear submodel references and add new keys
((Collection<Reference>) get(SUBMODELS)).clear();
submodels.stream().forEach(this::addSubmodelReferences);
}
public void setViews(Collection<IView> views) {
put(AssetAdministrationShell.VIEWS, views);
}
@Override
@SuppressWarnings("unchecked")
public Collection<IView> getViews() {
Collection<Map<String, Object>> coll = (Collection<Map<String, Object>>) get(AssetAdministrationShell.VIEWS);
return coll.stream().map(View::createAsFacade).collect(Collectors.toSet());
}
public void setConceptDictionary(Collection<IConceptDictionary> dictionaries) {
put(AssetAdministrationShell.CONCEPTDICTIONARY, dictionaries);
}
@Override
@SuppressWarnings("unchecked")
public Collection<IConceptDictionary> getConceptDictionary() {
Collection<Map<String, Object>> coll = (Collection<Map<String, Object>>) get(
AssetAdministrationShell.CONCEPTDICTIONARY);
return coll.stream().map(ConceptDictionary::createAsFacade).collect(Collectors.toSet());
}
@Override
public Map<String, ISubModel> getSubModels() {
throw new RuntimeException("getSubModels on local copy is not supported");
}
@Override
public String getIdShort() {
return Referable.createAsFacade(this, getKeyElement()).getIdShort();
}
@Override
public String getCategory() {
return Referable.createAsFacade(this, getKeyElement()).getCategory();
}
@Override
public LangStrings getDescription() {
return Referable.createAsFacade(this, getKeyElement()).getDescription();
}
@Override
public IReference getParent() {
return Referable.createAsFacade(this, getKeyElement()).getParent();
}
public void setCategory(String category) {
Referable.createAsFacade(this, getKeyElement()).setCategory(category);
}
public void setDescription(LangStrings description) {
Referable.createAsFacade(this, getKeyElement()).setDescription(description);
}
public void setParent(IReference obj) {
Referable.createAsFacade(this, getKeyElement()).setParent(obj);
}
@Override
public void addSubModel(SubModel submodel) {
logger.trace("adding Submodel", submodel.getIdentification().getId());
setSubmodelParent(Collections.singletonList(submodel));
addSubmodelReferences(submodel);
}
@Override
public void removeSubmodel(IIdentifier id) {
// Currently not implemented since future of Submodel References in AAS is not clear
throw new FeatureNotImplementedException();
}
/**
* Allows addition of a concept description to the concept dictionary
*
* @param description
*/
@SuppressWarnings("unchecked")
public void addConceptDescription(IConceptDescription description) {
Collection<IConceptDictionary> dictionaries = (Collection<IConceptDictionary>) get(AssetAdministrationShell.CONCEPTDICTIONARY);
if (dictionaries.isEmpty()) {
dictionaries.add(new ConceptDictionary("defaultConceptDictionary"));
}
ConceptDictionary dictionary = (ConceptDictionary) dictionaries.iterator().next();
dictionary.addConceptDescription(description);
}
@Override
public Collection<IReference> getSubmodelReferences() {
return ReferenceHelper.transform(get(SUBMODELS));
}
public void setSubmodelReferences(Collection<IReference> references) {
put(SUBMODELS, references);
}
@SuppressWarnings("unchecked")
public void addSubmodelReference(IReference reference) {
Collection<Object> smReferences = (Collection<Object>) get(SUBMODELS);
smReferences.add(reference);
}
private void addSubmodelReferences(SubModel submodel) {
addSubmodelReference(submodel.getReference());
}
private KeyElements getKeyElement() {
return KeyElements.ASSETADMINISTRATIONSHELL;
}
/**
* Set reference of current AAS to each SubModel of a collection
* as a parent reference
*
* @param submodels collection of Submodels
*/
private void setSubmodelParent(Collection<SubModel> submodels) {
for (SubModel submodel : submodels) {
submodel.setParent(getReference());
}
}
@Override
public IReference getReference() {
return Identifiable.createAsFacade(this, getKeyElement()).getReference();
}
@Override
public ISubModel getSubmodel(IIdentifier id) {
throw new RuntimeException("getSubmodel on local copy is not supported");
}
}