blob: 9dbc2c7e9fe0feed2eeee26369eb388f45f12712 [file] [log] [blame]
package org.eclipse.basyx.components.aas.mongodb;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.basyx.aas.metamodel.api.IAssetAdministrationShell;
import org.eclipse.basyx.aas.metamodel.map.AssetAdministrationShell;
import org.eclipse.basyx.aas.restapi.api.IAASAPI;
import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration;
import org.eclipse.basyx.submodel.metamodel.api.reference.IKey;
import org.eclipse.basyx.submodel.metamodel.api.reference.IReference;
import org.eclipse.basyx.submodel.metamodel.map.identifier.Identifier;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable;
import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
/**
* Implements the IAASAPI for a mongoDB backend.
*
* @author espen
*/
public class MongoDBAASAPI implements IAASAPI {
private static final String DEFAULT_CONFIG_PATH = "mongodb.properties";
private static final String AASIDPATH = Identifiable.IDENTIFICATION + "." + Identifier.ID;
protected BaSyxMongoDBConfiguration config;
protected MongoOperations mongoOps;
protected String collection;
protected String aasId;
/**
* Receives the path of the configuration.properties file in it's constructor.
*
* @param configFilePath
*/
public MongoDBAASAPI(BaSyxMongoDBConfiguration config, String aasId) {
this.setConfiguration(config);
this.setAASId(aasId);
}
/**
* Receives the path of the .properties file in it's constructor from a resource.
*/
public MongoDBAASAPI(String resourceConfigPath, String aasId) {
config = new BaSyxMongoDBConfiguration();
config.loadFromResource(resourceConfigPath);
this.setConfiguration(config);
this.setAASId(aasId);
}
/**
* Constructor using default sql connections
*/
public MongoDBAASAPI(String aasId) {
this(DEFAULT_CONFIG_PATH, aasId);
}
public void setConfiguration(BaSyxMongoDBConfiguration config) {
this.config = config;
MongoClient client = MongoClients.create(config.getConnectionUrl());
this.mongoOps = new MongoTemplate(client, config.getDatabase());
this.collection = config.getAASCollection();
}
/**
* Sets the aas id, so that this API points to the aas with aasId. Can be changed
* to point to a different aas in the database.
*
* @param smId
*/
public void setAASId(String aasId) {
this.aasId = aasId;
}
/**
* Depending on whether the model is already in the db, this method inserts or replaces the existing data.
* The new aas id for this API is taken from the given aas.
*
* @param sm
*/
public void setAAS(AssetAdministrationShell aas) {
String id = aas.getIdentification().getId();
this.setAASId(id);
Query hasId = query(where(AASIDPATH).is(aasId));
// Try to replace if already present - otherwise: insert it
Object replaced = mongoOps.findAndReplace(hasId, aas, collection);
if (replaced == null) {
mongoOps.insert(aas, collection);
}
}
@Override
public IAssetAdministrationShell getAAS() {
Query hasId = query(where(AASIDPATH).is(aasId));
AssetAdministrationShell aas = mongoOps.findOne(hasId, AssetAdministrationShell.class, collection);
if (aas == null) {
throw new ResourceNotFoundException("The AAS " + aasId + " could not be found in the database.");
}
// Remove mongoDB-specific map attribute from AASDescriptor
aas.remove("_id");
return aas;
}
@Override
public void addSubmodel(IReference submodel) {
// Get AAS from db
Query hasId = query(where(AASIDPATH).is(aasId));
AssetAdministrationShell aas = mongoOps.findOne(hasId, AssetAdministrationShell.class, collection);
if (aas == null) {
throw new ResourceNotFoundException("The AAS " + aasId + " could not be found in the database.");
}
// Add reference
aas.addSubmodelReference(submodel);
// Update db entry
mongoOps.findAndReplace(hasId, aas, collection);
}
@Override
public void removeSubmodel(String id) {
// Get AAS from db
Query hasId = query(where(AASIDPATH).is(aasId));
AssetAdministrationShell aas = mongoOps.findOne(hasId, AssetAdministrationShell.class, collection);
if (aas == null) {
throw new ResourceNotFoundException("The AAS " + aasId + " could not be found in the database.");
}
// Remove reference
Collection<IReference> smReferences = aas.getSubmodelReferences();
// Reference to submodel could be either by idShort (=> local) or directly via
// its identifier
for (Iterator<IReference> iterator = smReferences.iterator(); iterator.hasNext();) {
IReference ref = iterator.next();
List<IKey> keys = ref.getKeys();
IKey lastKey = keys.get(keys.size() - 1);
String idValue = lastKey.getValue();
// remove this reference, if the last key points to the submodel
if (idValue.equals(id)) {
iterator.remove();
break;
}
}
// Update db entry
mongoOps.findAndReplace(hasId, aas, collection);
}
}