blob: bffc13041e8eaf532272653bfab1c5418433ccc1 [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2004, 2007 Boeing
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Boeing - initial API and implementation
**********************************************************************/
package org.eclipse.osee.ote.message.elements;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import org.eclipse.osee.ote.core.environment.interfaces.ITimeout;
import org.eclipse.osee.ote.message.Message;
import org.eclipse.osee.ote.message.MessageSystemException;
import org.eclipse.osee.ote.message.data.MessageData;
import org.eclipse.osee.ote.message.enums.DataType;
/**
* @author Ryan D. Brooks
* @author Andrew M. Finkbeiner
*/
public abstract class Element implements ITimeout {
// protected final Message msg;
private final WeakReference<Message> msg;
protected String elementName;
private volatile boolean timedOut;
private final List<Object> elementPath;
private final String fullName;
protected final int byteOffset;
protected int lsb;
protected final MessageData messageData;
protected int msb;
protected final int originalMsb;
protected final int originalLsb;
private String elementPathAsString;
public Element(Message msg, String elementName, MessageData messageData, int byteOffset, int msb, int lsb, int originalMsb, int originalLsb) {
this.msg = new WeakReference<>(msg);
this.elementName = elementName;
this.messageData = messageData;
this.byteOffset = byteOffset;
this.lsb = lsb;
this.msb = msb;
this.originalLsb = originalLsb;
this.originalMsb = originalMsb;
elementPath = new ArrayList<>();
fullName = (msg != null ? msg.getName() : messageData.getName()) + "." + this.elementName;
}
public Element(Message msg, String elementName, MessageData messageData, int bitOffset, int bitLength) {
this(msg, elementName, messageData, bitOffset / 8, 0, 0, 0, 0);
this.msb = bitOffset % 8;
this.lsb = msb + bitLength - 1;
}
public Element(Message msg, String elementName, MessageData messageData, int byteOffset, int msb, int lsb) {
this(msg, elementName, messageData, byteOffset, msb, lsb, msb, lsb);
}
public int getMsb() {
return msb;
}
public int getLsb() {
return lsb;
}
public int getByteOffset() {
return byteOffset;
}
public MessageData getMsgData() {
return messageData;
}
public int getBitLength() {
return Math.abs(getMsb() - getLsb()) + 1;
}
public int getStartingBit() {
return getByteOffset() * 8 + Math.min(getMsb(), getLsb());
}
/*
* protected void set(TestEnvironmentAccessor accessor, long value) { if (accessor != null) {
* accessor.getLogger().methodCalledOnObject(accessor, this.getFullName(), (new MethodFormatter()).add(value)); }
* ((MemHolder) current.get()).getMem().s.setLong(value); if (accessor != null) {
* accessor.getLogger().methodEnded(accessor); } }
*/
/**
* @return Returns full name string.
*/
public String getFullName() {
return fullName;
}
public String getName() {
return this.elementName;
}
public String getDescriptiveName() {
return this.elementName;
}
/**
* @return Returns the msg.
*/
public Message getMessage() {
return msg.get();
}
public String getElementName() {
return elementName;
}
@Override
public boolean isTimedOut() {
return this.timedOut;
}
@Override
public void setTimeout(boolean timeout) {
this.timedOut = timeout;
}
public DataType getType() {
return messageData.getPhysicalIoType();
}
/**
* @return Returns the lsb.
*/
public int getOriginalLsb() {
return originalLsb;
}
/**
* @return Returns the msb.
*/
public int getOriginalMsb() {
return originalMsb;
}
private int calculateBitsToShift() {
int size = lsb - msb + 1;
return 32 - size;
}
private int calculateLongBitsToShift() {
int size = lsb - msb + 1;
return 64 - size;
}
protected int signExtend(int value) {
int bitsToShift = calculateBitsToShift();
return value << bitsToShift >> bitsToShift;
}
protected int removeSign(int value) {
int bitsToShift = calculateBitsToShift();
return value << bitsToShift >>> bitsToShift;
}
protected long removeSign(long value) {
int bitsToShift = calculateLongBitsToShift();
return value << bitsToShift >>> bitsToShift;
}
/**
* @return whether this message maps solely to PubSub
*/
public boolean isNonMappingElement() {
return false;
}
/**
* Looks for the element matching this elements name inside one of the messages passed
*
* @param messages Those messages mapped to a certain physical type, one of whom contains a mapping to this element
* @return An element of one of the messages passed with the same name as this element or this element if no match is
* found.
*/
@SuppressWarnings("rawtypes")
public Element findElementInMessages(Collection<? extends Message> messages) {
for (Message currentMessage : messages) {
// System.out.println("SwitchMessages" + currentMessage.getMessageName());
Element el = currentMessage.getElement(this.getElementPath());
if (el != null && currentMessage.isValidElement(this, el)) {
return el;
}
}
return this.getNonMappingElement();
}
public Element switchMessages(Collection<? extends Message> messages) {
for (Message currentMessage : messages) {
// System.out.println("SwitchMessages" + currentMessage.getMessageName());
Element el = currentMessage.getElement(this.getElementPath());
if (el != null && currentMessage.isValidElement(this, el)) {
return el;
}
}
return this.getNonMappingElement();
}
protected void sendMessage() {
this.getMessage().send();
}
/**
* This method returns a properly formatted string that describes the range and inclusive/exclusive properties of
* each end of the range.
*
* @param minValue The minimum value of the range.
* @param minInclusive If the minumum value of the range is inclusive. If true the actual value must not < and not =
* to the range value.
* @param maxValue The maximum value of the range.
* @param maxInclusive If the maximum value of the range is inclusive. If true the actual value must not > and not =
* to the range value.
* @return the string holding "[", "]", "(", or ")"
*/
protected static String expectedRangeString(Object minValue, boolean minInclusive, Object maxValue, boolean maxInclusive) {
// A means for a return value
String retVal;
// Start with the proper symbol for the lower bound
if (minInclusive) {
retVal = "[";
} else {
retVal = "(";
}
// Add in the minimum and maximum values
retVal += minValue + " .. " + maxValue;
// End with the proper symbol for the upper bound
if (maxInclusive) {
retVal += "]";
} else {
retVal += ")";
}
// Return the formatted string
return retVal;
}
protected abstract Element getNonMappingElement();
protected void throwNoMappingElementException() {
throw new MessageSystemException(
"The element " + msg.get().getName() + "." + elementName + " does not exist for the message's current MemType="+msg.get().getMemType()+"!! " + "\nIt shouldn't be used for this environment type!!",
Level.SEVERE);
}
/**
* @return the elementPath
*/
public List<Object> getElementPath() {
return elementPath;
}
public void addPath(Object... objs) {
for (Object obj : objs) {
elementPath.add(obj);
}
elementPath.add(this.getName());
}
@Override
public String toString() {
return elementName;
}
/**
* Zeroize the data for this element (not the mask).
*/
public void zeroize() {
getMsgData().getMem().setLong(0L, byteOffset, msb, lsb);
}
public void visit(IElementVisitor visitor) {
visitor.asGenericElement(this);
}
public String getElementPathAsString() {
if (elementPathAsString == null) {
StringBuilder sb = new StringBuilder();
for (int i = 1; i < elementPath.size(); i++) {
Object obj = elementPath.get(i);
if (obj instanceof String) {
sb.append(obj);
} else if (obj instanceof Integer) {
sb.delete(sb.length() - 1, sb.length());
sb.append("[");
sb.append(((Integer) obj).intValue());
sb.append("]");
}
if (i < elementPath.size() - 1) {
sb.append(".");
}
}
elementPathAsString = sb.toString();
}
return elementPathAsString;
}
}