/*******************************************************************************
* Copyright (c) 2009, 2010 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
******************************************************************************/
package org.eclipse.ocl.examples.impactanalyzer.benchmark.preparation.tasks;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.ocl.ecore.OCL;
import org.eclipse.ocl.ecore.internal.OCLStandardLibraryImpl;
import org.eclipse.ocl.ecore.opposites.OppositeEndFinder;
import org.eclipse.ocl.examples.impactanalyzer.benchmark.preparation.ocl.OCLExpressionWithContext;
/** It is not necessary that a all instance evaluation is measured multiple times for one single model size
* Therefore different benchmark jobs for one model size share the same all instance evaluation measurement.
*
* @author
*/
@SuppressWarnings("restriction")
public class AllInstanceEvaluationMeasurement {
// Model for which a all instance call is measured
private final Resource model;
private final LinkedHashMap<String, String> additionalInformation = new LinkedHashMap<String, String>();
private final OppositeEndFinder oppositeEndFinder;
private Collection<EObject> allInstances = null;
private boolean hasBeenMeasuredAlready = false;
private final OCL ocl;
private final OCLExpressionWithContext expression;
public AllInstanceEvaluationMeasurement(OppositeEndFinder oppositeEndFinder, Resource model, OCLExpressionWithContext expression) {
this.oppositeEndFinder = oppositeEndFinder;
this.model = model;
this.expression = expression;
this.ocl = org.eclipse.ocl.examples.impactanalyzer.util.OCL.newInstance(oppositeEndFinder);
}
public LinkedHashMap<String, String> getAdditionalInformation(){
assert hasBeenMeasuredAlready == true;
return additionalInformation;
}
public void measureAllInstances() {
assert hasBeenMeasuredAlready == false;
//Prerun to be sure that index is initialized
oppositeEndFinder.getAllInstancesSeenBy(expression.getContext(), model);
long beforeAllInstances = System.nanoTime();
allInstances = oppositeEndFinder.getAllInstancesSeenBy(expression.getContext(), model);
long afterAllInstances = System.nanoTime();
additionalInformation.put("allInstanceExecTime", String.valueOf(afterAllInstances - beforeAllInstances));
additionalInformation.put("noAllInstances", String.valueOf(allInstances.size()));
//Only do this when activating. More runs are far too expensive.
Collection<Object> allInstancesEvaluationResult = new LinkedList<Object>();
((AllInstanceCallCountingOppositeEndFinder)oppositeEndFinder).resetAll();
long timeToEvaluate = 0;
long timeToEvaluateWithoutInvalidResults = 0;
for(EObject affectedElement : allInstances){
//Prerun in order to eliminate caching effects
ocl.evaluate(affectedElement, expression.getExpression());
long before = System.nanoTime();
Object result = ocl.evaluate(affectedElement, expression.getExpression());
long after = System.nanoTime();
allInstancesEvaluationResult.add(result);
timeToEvaluate = timeToEvaluate + (after - before);
if(result == null || !result.equals(OCLStandardLibraryImpl.INSTANCE.getInvalid())){
timeToEvaluateWithoutInvalidResults = timeToEvaluateWithoutInvalidResults + (after - before);
}
}
int allInstancesCalls = ((AllInstanceCallCountingOppositeEndFinder)oppositeEndFinder).getAllInstancesCalled();
additionalInformation.put("noAllInstanceEvalAllInstanceCalls", String.valueOf(allInstancesCalls));
int findOppositeEndsCalls = ((AllInstanceCallCountingOppositeEndFinder)oppositeEndFinder).getFindOppositeEndsCalled();
additionalInformation.put("noAllInstanceFindOppositeEndsCalls", String.valueOf(findOppositeEndsCalls));
int getAllOppositeEndsCalls = ((AllInstanceCallCountingOppositeEndFinder)oppositeEndFinder).getGetAllOppositeEndsCalled();
additionalInformation.put("noAllInstanceGetAllOppositeEndsCalls", String.valueOf(getAllOppositeEndsCalls));
((AllInstanceCallCountingOppositeEndFinder)oppositeEndFinder).resetAll();
additionalInformation.put("allInstanceEvalTime", String.valueOf(new Long(timeToEvaluate)));
additionalInformation.put("allInstanceEvalTimeWoInvalid", String.valueOf(new Long(timeToEvaluateWithoutInvalidResults)));
additionalInformation.put("allInstanceNoInvalidEvals", String.valueOf(getNoOfInvalidEvaluations(allInstancesEvaluationResult)));
hasBeenMeasuredAlready = true;
}
public void setHasBeenMeasuredAlready(boolean hasBeenMeasuredAlready) {
this.hasBeenMeasuredAlready = hasBeenMeasuredAlready;
}
public boolean isHasBeenMeasuredAlready() {
return hasBeenMeasuredAlready;
}
public int getNoOfInvalidEvaluations(Collection<Object> evaluationResult) {
int invalidEvaluationCounter = 0;
for(Object result : evaluationResult){
if(result != null && result.equals(OCLStandardLibraryImpl.INSTANCE.getInvalid())){
invalidEvaluationCounter++;
}
}
return invalidEvaluationCounter;
}
}