Commit 0224b9c4 authored by Shirley Crompton's avatar Shirley Crompton
Browse files

cleaned up code after Christian's changes. Mapper now overwrite CP

model rather than create a new version.  Also Junit'ed the updated code.
parent dfe4dd4a
......@@ -27,6 +27,8 @@ import eu.paasage.upperware.metasolver.solutionListener;
import eu.paasage.upperware.metasolver.RPListener;
import eu.paasage.upperware.metasolver.metricsListener;
import eu.paasage.upperware.metasolver.metrics.Mapper;
import eu.paasage.upperware.metasolver.util.CdoTool;
import eu.paasage.upperware.metasolver.util.CpModelTool;
import org.apache.log4j.Logger;
import org.eclipse.emf.cdo.view.CDOView;
......@@ -48,34 +50,39 @@ public class metasolver{
long mapResult = map.mapMetricVariables(CPmodID);
*/
CDOClient cdoClient = new CDOClient();
cdoClient.registerPackage(ApplicationPackage.eINSTANCE);
cdoClient.registerPackage(CpPackage.eINSTANCE);
cdoClient.registerPackage(TypesPackage.eINSTANCE);
cdoClient.registerPackage(TypesPaasagePackage.eINSTANCE);
cdoClient.registerPackage(TypePackage.eINSTANCE);
CDOView cdoView = cdoClient.openView();
log.info("Reading CP model from CDO...");
EList<EObject> contentsPC = cdoView.getResource(CPmodID).getContents();
log.info("Extracting models...");
// PaasageConfiguration paasageConfiguration = (PaasageConfiguration) contentsPC.get(0);
ConstraintProblem cp = (ConstraintProblem) contentsPC.get(1);
CdoTool.registerPackages(cdoClient);
// cdoClient.registerPackage(ApplicationPackage.eINSTANCE);
// cdoClient.registerPackage(CpPackage.eINSTANCE);
// cdoClient.registerPackage(TypesPackage.eINSTANCE);
// cdoClient.registerPackage(TypesPaasagePackage.eINSTANCE);
// cdoClient.registerPackage(TypePackage.eINSTANCE);
CDOView cdoView = cdoClient.openView();
HashMap<String, String> mets=null;
// Handling Metric passed as input file (to be updated for reading from CDO)
if(metricFile!=null){
//get Metrics
mets = readFile1(metricFile);
//check Metrics
boolean check = checkMets(mets, cp);
if (check)
System.out.println("MetricFile validated");
else
System.out.println("MetricFile not validated. Proceeding anyway");
//
try{
log.info("Reading CP model from CDO...");
EList<EObject> contentsPC = cdoView.getResource(CPmodID).getContents();
log.info("Extracting models...");
// PaasageConfiguration paasageConfiguration = (PaasageConfiguration) contentsPC.get(0);
ConstraintProblem cp = CpModelTool.getCPModel(contentsPC);
// Handling Metric passed as input file (to be updated for reading from CDO)
if(metricFile!=null){
//get Metrics
mets = readFile1(metricFile);
//check Metrics
boolean check = checkMets(mets, cp);
if (check)
System.out.println("MetricFile validated");
else
System.out.println("MetricFile not validated. Proceeding anyway");
}
}catch(Exception e){
System.out.println("Error reading ConstraintProblem from CDO : " + e.getMessage() + "!");
}finally{
log.info("Closing CDO connection...");
cdoView.close();
cdoClient.closeSession();
}
log.info("Closing CDO...");
cdoView.close();
cdoClient.closeSession();
log.info("Mapping metric variables...");
......
......@@ -20,6 +20,7 @@ import org.eclipse.emf.ecore.EObject;
import com.eclipsesource.json.JsonObject;
import eu.paasage.mddb.cdo.client.CDOClient;
import eu.paasage.upperware.metamodel.cp.ConstraintProblem;
import eu.paasage.upperware.metamodel.cp.CpFactory;
import eu.paasage.upperware.metamodel.cp.MetricVariable;
......@@ -56,143 +57,127 @@ public class Mapper {
private CdoTool utils;
/**
* Construct an instance -- remove as we need a cpModelId
*/
// public Mapper() {
// }
/**
* Construct an instance with the target CP Model resource id */
* Construct an instance with the target CP Model resource id
* */
public Mapper(String resId) {
// I think this may change at runtime as rule processor clones the cp_model
// rather than updating it. The new version will have a new resource id
// Also, we may need to update the CP model expressions too, this requires creating a new version to avoid
// overwriting previous state
// 11Dec15 Mapper now overwrites cp model rather than creating a new version. One id is sufficient
this.cpModelId = resId;
}
/**
* Construct an instance with the target CP Model resource id
public Mapper(String resId) {
// I think this may change at runtime as rule processor clones the cp_model
// rather than updating it. The new version will have a new resource id
// Also, we may need to update the CP model expressions too, this requires creating a new version to avoid
// overwriting previous state
this.cpModelId = resId;
}*/
/**
* This method is used for preparing a CP model for first deployment. There
* are no running metrics and a default constant value is assigned to each
* metric variable listed in the model. If there are no metric variables in
* the CPModel, the solution timestamp value will be 0.
* A wrapper for calling the {{@link #mapMetricVariables(HashMap)} method for a first deployment.
* <p>
* @param resId
* the target CP Model resource id
* id of the target {@link eu.paasage.upperware.metamodel.cp.ConstraintProblem <em>ConstraintProblem</em>}
* @return a {@link com.eclipsesource.json.JsonObject <em>JsonObject</em>} containing the
* new resource ID and the solution timestamp
* @throws MetricMapperException
* new resource ID and the solution timestamp.
* @throws {@link eu.paasage.upperware.metasolver.exception.MetricMapperException <em>MetricMapperException</em>}
* on processing error
*/
public JsonObject mapMetricVariables() throws MetricMapperException {
return this.mapMetricVariables(null);
}
/**
* This method is used to prepare the CP Model for re&#45;deployment. The CP
* model is updated with the metric variable values provided in the input
* {@link java.util.HashMap <em>HashMap</em>}
* Prepare the CP Model for a new deployment. There are no running metrics
* and a default constant value is assigned to each metric variable listed in the constraint model.
* <p>
* @param resId
* the target CP Model resource id
* @param metrics
* a {@link java.util.HashMap <em>HashMap</em>} of the metric
* variables and associated values to update
* @return a {@link com.eclipsesource.json.JsonObject <em>JsonObject</em>} containing the
* new resource ID and the solution timestamp
* @throws MetricMapperException
* on processing error
* @param cp the {@link eu.paasage.upperware.metamodel.cp.ConstraintProblem <em>ConstraintProblem</em>} to solve
* @param solution the last {@link eu.paasage.upperware.metamodel.cp.Solution <em>Solution</em>} object in the model.
* @return true if the {@link eu.paasage.upperware.metamodel.cp.ConstraintProblem <em>ConstraintProblem</em>} has been modified, else false.
*/
private boolean initWithDefaultMetricVariable(ConstraintProblem cp, Solution solution)
{
boolean updatedCP=false;
for (MetricVariable mv : cp.getMetricVariables())
{
if (CPModelTool.searchMetricValue(solution, mv) == null)
{
//Theoretically CP_generator should have set default values for all the metric variable upstream
for (MetricVariable mv : cp.getMetricVariables()){
if (CPModelTool.searchMetricValue(solution, mv) == null){
// create it
CpModelTool.setConstantValue(mv, solution); // TO CHECK !!!
updatedCP=true;
log.debug("...about to call setConstantValue with solution(" + solution.getTimestamp() + ") and metric variable(" + mv.getId() );
CpModelTool.setConstantValue(mv, solution);
updatedCP = true;
}
}
return updatedCP;
}
private boolean initWithMetrics(ConstraintProblem cp, Solution lastSolution, Solution newSolution, HashMap<String, String> metrics )
/**
* Update the {@link eu.paasage.upperware.metamodel.cp.MetricVariableValue <em>MetricVariableValue</em>} with the
* incoming ones or copy the existing ones from the previous {@link eu.paasage.upperware.metamodel.cp.Solution <em>Solution</em>} object
* <p>
* @param cp the target {@link eu.paasage.upperware.metamodel.cp.ConstraintProblem <em>ConstraintProblem</em>}
* @param newSolution the new {@link eu.paasage.upperware.metamodel.cp.Solution <em>Solution</em>} object used to store the values
* @param lastSolution the last {@link eu.paasage.upperware.metamodel.cp.Solution <em>Solution</em>} object in the cp model
* @param metrics a {@java.util.HashMap <em>HashMap</em>} containing the key value pairs of the incoming metric variables.
* @return true if the {@link eu.paasage.upperware.metamodel.cp.ConstraintProblem <em>ConstraintProblem</em>} has been modified, else false.
* @throw {@link eu.paasage.upperware.metasolver.exception.MetricMapperException <em>MetricMapperException</em>}
* on processing error
*/
private boolean initWithMetrics(ConstraintProblem cp, Solution lastSolution, Solution newSolution, HashMap<String, String> metrics ) throws MetricMapperException
{
boolean updatedCP=false;
boolean updatedCP = false;
// process the incoming metric variable values
List<MetricVariable> cp_MVs = cp.getMetricVariables();
Set<String> metricVariables = metrics.keySet();
//process the incoming metric variables first
for (String mvName : metricVariables) {
log.debug("the current metric variable is : " + mvName + "...");
//look for the owner - the metric variable
MetricVariable currentMV = CpModelTool.getMetricVariable(mvName, cp_MVs);
// create the new value using the incoming version
MetricVariableValue value = CpModelTool.createMVV(currentMV, metrics.get(mvName));
// TODO: CHECK IF IT DOES NOT ALREAD EXIST
//
newSolution.getMetricVariableValue().add(value);
updatedCP = true;
}
//need to copy the existing values for those not included in the update
if(cp_MVs.size() > metrics.size()){ //if there are more metric variables than those provided
//now copy the existing values for those not included in the update
if(cp_MVs.size() > metrics.size()){ //if there are more metric variables than those incoming
for(MetricVariable cp_mv : cp_MVs){
//System.out.println("current metricVariable id is : " + cp_mv.getId() + "....");
log.debug("current metricVariable id is : " + cp_mv.getId() + "....");
//is the current cp metric variable in the incoming set
if(!metricVariables.contains(cp_mv.getId())){
log.debug("current metric variable(" + cp_mv.getId() + ") is not in the incoming set....");
//find the existing value (there should always be one, either initial constant value or the previous runtime value
//find the existing value (there should always be one, either the initial constant value or the previous runtime value
MetricVariableValue oldValue = CPModelTool.searchMetricValue(lastSolution, cp_mv);
//
if(oldValue != null){
log.debug("... trying to copy old value to new solution for : " + cp_mv.getId());
//needs to clone a new MetricVariableValue ob
log.debug("... copying old value to new solution for : " + cp_mv.getId());
//need to clone a new MetricVariableValue object
MetricVariableValue newValueObj = CpModelTool.createMVV(cp_mv, oldValue.getValue());
// TODO: CHECK IF IT DOES NOT ALREAD EXIST
//
newSolution.getMetricVariableValue().add(newValueObj);
updatedCP = true;
}else{//failed to find the old value
throw new MetricMapperException("Failed to find existing metric variable value for : " + cp_mv.getId());
}
}
}
}
return updatedCP;
}
/**
* Update the {@link eu.paasage.upperware.metamodel.cp.MetricVariableValue <em>MetricVariableValue</em>}
* <p>
* @param metrics a {@java.util.HashMap <em>HashMap</em>} containing the key value pairs of the incoming metric variables.
* @return a {@link com.eclipsesource.json.JsonObject <em>JsonObject</em>} containing the
* new resource ID and the solution timestamp.
* @throws {@link eu.paasage.upperware.metasolver.exception.MetricMapperException <em>MetricMapperException</em>}
* on processing error
*/
public JsonObject mapMetricVariables(HashMap<String, String> metrics) throws MetricMapperException {
JsonObject jObj = new JsonObject(); //keys are "id" (String) and "solution_tmp" (long)
jObj.add("id", this.cpModelId);
if (this.utils == null) {
this.utils = CdoTool.getInstance();
}
// start the cdo-client
try
{
this.utils.openCDOSession();
// load the resource in memory and get the cp model
CDOTransaction trans = CdoTool.getCDOClient().openTransaction();
log.info("Reading CDO resId: "+this.cpModelId);
CDOResource res = trans.getResource(this.cpModelId);
log.info("Res: "+res);
EList<EObject> model_contents = res.getContents(); // cloner may return an empty list
CDOClient cdoClient = new CDOClient();
CdoTool.registerPackages(cdoClient);
// to overwrite, we need to get the target object w/n a transaction
CDOTransaction trans = cdoClient.openTransaction();
//
try{
log.info("Reading CDO resId: "+ this.cpModelId);
CDOResource res = trans.getResource(CdoTool.mapCdoId(this.cpModelId));
log.info("Res: " + res);
EList<EObject> model_contents = res.getContents(); // may get an empty list
ConstraintProblem cp = CpModelTool.getCPModel(model_contents);
if (cp == null) {
throw new MetricMapperException("failed to extract ConstraintModel from the resource(" + this.cpModelId + ")");
......@@ -205,66 +190,68 @@ public class Mapper {
Solution lastSolution = CPModelTool.searchLastSolution(cp.getSolution());
Solution newSolution = null;
Long timestamp;
// If not solution, create an empty one
if ((lastSolution == null) || (metrics!=null))
{
// 11Dec15 either no last solution or has metrics
// there is always a last solution, so we rely on the 2nd condition
log.debug("last solution is null? " + (lastSolution == null ? true : false));
log.debug("metrics hm is null? " + (metrics == null ? true : false));
//
if ((lastSolution == null) || (metrics !=null)){
log.debug("metrics hm != null ...");
//only applies to reconfig
Solution sol = CpFactory.eINSTANCE.createSolution();
Long ts = System.currentTimeMillis();
sol.setTimestamp(ts);
cp.getSolution().add(sol);
try {
log.debug("Commiting a new empty Solution...");
trans.commit();
} catch (CommitException e) {
throw new MetricMapperException("Error when commiting an empty solution to CDO");
}
//chunk up commits to avoid dirty state
log.debug("Commiting a new empty Solution...");
trans.commit();
// need to reload sol ?
newSolution = sol;
timestamp = ts;
} else {
//11Dec15, this implies the new deployment case. We rely on CP Generator doing the deed
timestamp = lastSolution.getTimestamp();
}
// Completing jObj
jObj.add("solution_tmp", timestamp); // milp-solver needs this
//
// Check if there are some metric variables
List<MetricVariable> mvs = cp.getMetricVariables();
if ((mvs == null) || mvs.isEmpty()) {
// Nothing to do?
// Nothing to do? but the cp model will always have an empty solution
log.info("CP model in " + this.cpModelId + " has no Metric Variable entities...");
trans.close();
return jObj;
}
//there are metric variables
log.info(mvs.size() + " metric variables retrived from CP model in " + this.cpModelId + "...");
}
//there are metric variables in the CP model
log.info(mvs.size() + " metric variables retrieved from CP model in " + this.cpModelId + "...");
//
boolean updatedCP;
if (metrics == null)
if (metrics == null){ //new deployment, no running metrics
log.debug("..no metrics HM, calling initWithDefaultMetricVariable....");
updatedCP = this.initWithDefaultMetricVariable(cp, lastSolution);
else
}else{ //reconfig
log.debug("..have metrics HM, calling initWithMetrics....");
updatedCP = this.initWithMetrics(cp, lastSolution, newSolution, metrics);
if (updatedCP)
{
try {
log.debug("Commiting Metric Variable Solution...");
trans.commit();
} catch (CommitException e) {
throw new MetricMapperException("Error when commiting an empty solution to CDO");
}
}
if (updatedCP){
//
log.debug("Commiting Metric Variable Solution...");
trans.commit();
trans.close();
}
trans.close();
} catch (CommitException e) {
throw new MetricMapperException("Error when commiting an empty solution to CDO : " + e);
}catch(MetricMapperException me){
throw me; //re-throw
}catch(Exception e){
log.error("Error trying to map metricVariableValues for new deployment : " + e.getMessage());
log.error("Error trying to map metricVariableValues: " + e.getMessage());
throw new MetricMapperException(e);
} finally {
this.utils.closeCDOSession();
}finally{
//make sure that it is closed
if(!trans.isClosed()){
trans.close();
}
}
return jObj;
}
......@@ -274,7 +261,6 @@ public class Mapper {
/**
* Getter for the {@link #cpModelId <em>cpModelId</em>}
* <p>
*
* @return the cpModelId
*/
public String getCpModelId() {
......@@ -284,7 +270,6 @@ public class Mapper {
/**
* Setter for the {@link #cpModelId <em>cpModelId</em>}
* <p>
*
* @param cpModelId
* the cpModelId to set
*/
......
......@@ -8,51 +8,65 @@
package eu.paasage.upperware.metasolver.util;
import java.util.List;
import org.apache.log4j.Logger;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CommitException;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
//import org.eclipse.emf.cdo.transaction.CDOTransaction;
//import org.eclipse.emf.cdo.util.CommitException;
//import org.eclipse.emf.common.util.EList;
//import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import eu.paasage.mddb.cdo.client.CDOClient;
//import eu.paasage.upperware.cp.cloner.CPCloner;
import eu.paasage.upperware.cp.cloner.CDOClientExtended;
import eu.paasage.upperware.cp.cloner.CPCloner;
//import eu.paasage.upperware.cp.cloner.CPCloner;
//import eu.paasage.upperware.cp.cloner.CDOClientExtended;
import eu.paasage.upperware.metamodel.application.ApplicationPackage;
import eu.paasage.upperware.metamodel.cp.ConstraintProblem;
//import eu.paasage.upperware.metamodel.cp.ConstraintProblem;
import eu.paasage.upperware.metamodel.cp.CpPackage;
import eu.paasage.upperware.metamodel.cp.Solution;
//import eu.paasage.upperware.metamodel.cp.Solution;
import eu.paasage.upperware.metamodel.types.TypesPackage;
import eu.paasage.upperware.metamodel.types.typesPaasage.TypesPaasagePackage;
import fr.inria.paasage.saloon.camel.mapping.MappingPackage;
import fr.inria.paasage.saloon.camel.ontology.OntologyPackage;
/**
* A singleton utility to help interact with the CDO server.
* A utility to help interaction with the CDO server.
* <p>
* @author Shirley Crompton
* org UK Science and Technology Facilities Council
*/
public final class CdoTool {
//code updated by Christian to overwrite existing CP model directly using transaction
//CP cloner and generator are no longer required.
//
//
/** log4j message logger */
protected static Logger log = Logger.getLogger(CdoTool.class);
/** singleton instance of CDOUtils */
private static CdoTool instance = null;
//private static CdoTool instance = null;
/** CP Cloner CDO client */
// private static CDOClientExtended extendedClient = null;
//private static CDOClientExtended extendedClient = null;
/** CP Cloner */
// private static CPCloner cloner = null;
/** CDO Client */
private static CDOClient cdoClient = null;
/**
private String resId = null;*/
//private static CDOClient cdoClient = null;
/**
* Private constructor
*/
private CdoTool() {
// default private constructor
}
......@@ -60,7 +74,7 @@ public final class CdoTool {
* Construct an instance.
* <p>
* @return an instance of the class.
*/
public static CdoTool getInstance()
{
if(instance == null){
......@@ -80,46 +94,95 @@ public final class CdoTool {
{
return cdoClient;
}
public void openCDOSession()
{
if(cdoClient == null)
{
cdoClient = new CDOClient();
*/
public static void registerPackages(CDOClient cdoClient){
//add the cp packages
log.debug("Instantiating cdoClient and registering packages...");
cdoClient = new CDOClient();
// cdoClient.registerPackage(TypesPackage.eINSTANCE);
cdoClient.registerPackage(ApplicationPackage.eINSTANCE);
log.info("Init ApplicationPackag");
cdoClient.registerPackage(TypesPaasagePackage.eINSTANCE);
log.info("Init TypesPaasagePackage");
cdoClient.registerPackage(TypesPackage.eINSTANCE);
log.info("Init TypesPackage");
cdoClient.registerPackage(CpPackage.eINSTANCE);
log.info("Init CpPackage");
cdoClient.registerPackage(OntologyPackage.eINSTANCE);
log.info("Init OntologyPackage");
cdoClient.registerPackage(MappingPackage.eINSTANCE);
log.info("Init MappingPackage");
cdoClient.registerPackage(ApplicationPackage.eINSTANCE);
log.info("Init ApplicationPackag");
cdoClient.registerPackage(TypesPaasagePackage.eINSTANCE);
log.info("Init TypesPaasagePackage");
cdoClient.registerPackage(TypesPackage.eINSTANCE);
log.info("Init TypesPackage");
cdoClient.registerPackage(CpPackage.eINSTANCE);
log.info("Init CpPackage");
cdoClient.registerPackage(OntologyPackage.eINSTANCE);
log.info("Init OntologyPackage");
cdoClient.registerPackage(MappingPackage.eINSTANCE);
log.info("Init MappingPackage");
}
/**
* CP models are stored in CDO server under the upperware_models/ resource path.
* This function prefix model id with the required resource path.
* <p>
* @param current the current CP model identifier {@link java.lang.String <em>String</em>}
* @return the cleaned identifier {@link java.lang.String <em>String</em>}
* or null if current is null or empty
*/
public static String mapCdoId(String current){
if(current == null || current.isEmpty()){
log.error("cannot map Cdo Id, resId is null/empty!");
return null;
}
//
if(current.startsWith(CPCloner.CDO_SERVER_PATH)){
return current;
}else{
return CPCloner.CDO_SERVER_PATH + current;
}
}
/**
* An explicit method to close the cloner client CDO session and
* terminate the client.
*/
public void closeCDOSession(){
cdoClient.closeSession();
cdoClient = null;
log.info("closed client session and removed client...");
public void closeCDOSession(){
cdoClient.closeSession();
cdoClient = null;
log.info("closed client session and removed client...");
}
/**
* Get a CDO transaction object.
* <p>
* @return
public CDOTransaction getTransaction(){
if(cdoClient == null){
openCDOSession();
}
return cdoClient.openTransaction();
}
/**
* Retrieve the resource from the cdo server
* <p>
* @param resId resId Identifier of the target CDO resource
* @return the cloned resource as a {@link java.util.List <em>List</em>} of the
* {@link org.eclipse.emf.ecore.EObject <em>EObject</em>}
*/
// public List<EObject> getResource(String resId){