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