blob: fc0a02ad6b4d881764f9a6176843327d81db87de [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2018 CEA LIST
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
*****************************************************************************/
package org.eclipse.papyrus.moka.ease.semantics.proxy;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
/**
*This class is used to hold the reference to a Locus object and access to a given feature value of this object.
*It will copy and append the current value of this feature into the "values" list when "logValue" is called.
* It provides a getByteArray method for Double or Integer values allowing efficient data transfer between
* java and python.
*/
public class LoggedValue {
private static final String DOUBLE_TYPE = "Double";
private static final String INTEGER_TYPE = "Integer";
public String alias;
public MapProxy context;
public String loggedFeature;
public List<Object> values = new ArrayList<>();
String[] path;
public LoggedValue() {
}
/**
* @param variablePath : "." separated feature path starting from the context object
* @param alias : alias used for this variable in the log
* @param context : root object from which feature path is computed
*/
public LoggedValue(String variablePath, String alias, MapProxy context) {
this.alias = alias;
path = variablePath.split("\\.");
this.context = context;
loggedFeature = path[path.length - 1];
}
/**
* Gets the current locus object and feature and returns its value.
* The locus object as to be found for each call to getValue since it can change during the simulation
* @return : the current value of the logged feature
*/
public Object getValue() {
MapProxy owningProxy = context;
for (int i = 0; i < path.length - 1; i++) {
owningProxy = (MapProxy) owningProxy.get(path[i]);
}
return owningProxy.get(loggedFeature);
}
/**
* Get the current value and puts it in the values list
*/
public void logValue() {
values.add(getValue());
}
/**
* Function returning the values collection as a byte array, for java to python performance optimization
* Only works for Integer and Double types.
* Warning, the collection has to be homogeneous, if is it contains a mix of Double and Integer, data will be corrupted.
*
* @return a Byte array representation of the collection
*/
public byte[] getByteArray() {
int typeSize = 0;
if (DOUBLE_TYPE.equals(getType())) {
typeSize = Double.BYTES;
} else if (INTEGER_TYPE.equals(getType())) {
typeSize = Integer.BYTES;
}
if (typeSize != 0) {
ByteBuffer byteBuffer = ByteBuffer.allocate(typeSize * values.size());
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
if (DOUBLE_TYPE.equals(getType())){
for (Object obj : values) {
byteBuffer.putDouble((double) obj);
}
}else {
for (Object obj : values) {
byteBuffer.putInt((int) obj);
}
}
byte[] byteArray = byteBuffer.array();
return byteArray;
} else {
return null;
}
}
/**
* @return the alias of the logged feature value
*/
public String getAlias() {
return alias;
}
/**
* This function returns the collection of recorded values.
* It can be directly called from Python, but will be about 50 times slower than {@link #getByteArray()} to initialize numpy arrays
* @return the list of values
*/
public List<Object> getValues() {
return values;
}
/**
* Tries to guess the type of the logged object using the first object of the values list.
* This function will be used from python side to know if we can use the {@link #getByteArray()} to initialize numpy arrays
* @return : "Double", "Integer" or "Object"
*/
public String getType() {
if (!values.isEmpty()) {
Object first = values.get(0);
if (first instanceof Double) {
return DOUBLE_TYPE;
} else if (first instanceof Integer) {
return INTEGER_TYPE;
}
}
return "Object";
}
}