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