All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.gsi.serializer.spi.WireDataFieldDescription Maven / Gradle / Ivy

package de.gsi.serializer.spi;

import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.gsi.serializer.DataType;
import de.gsi.serializer.FieldDescription;
import de.gsi.serializer.IoSerialiser;
import de.gsi.serializer.utils.ClassUtils;

/**
 * Field header descriptor
 * 
 * @author rstein
 */
public class WireDataFieldDescription implements FieldDescription {
    private static final Logger LOGGER = LoggerFactory.getLogger(WireDataFieldDescription.class);
    private final String fieldName;
    private final int fieldNameHashCode;
    private final DataType dataType;
    private final List children = new ArrayList<>();
    private final FieldDescription parent;
    private final int fieldStart;
    private final int fieldDataStart;
    private final int dataStartOffset;
    // local references to source buffer needed for parsing
    private final IoSerialiser ioSerialiser;
    private String fieldUnit;
    private String fieldDescription;
    private String fieldDirection;
    private List fieldGroups;
    private int dataSize;

    /**
     * Constructs new serializer field header
     *
     * @param source the referenced IoBuffer (if any)
     * @param parent the optional parent field header (for cascaded objects)
     * @param fieldNameHashCode the fairly-unique hash-code of the field name,
     *                         N.B. checked during 1st iteration against fieldName, if no collisions are present then
     *                         this check is being suppressed
     * @param fieldName the clear text field name description
     * @param dataType the data type of that field
     * @param fieldStart the absolute buffer position from which the field header can be parsed
     * @param dataStartOffset the position from which the actual data can be parsed onwards
     * @param dataSize the expected number of bytes to skip the data block
     */
    public WireDataFieldDescription(final IoSerialiser source, final FieldDescription parent, final int fieldNameHashCode, final String fieldName, final DataType dataType, //
            final int fieldStart, final int dataStartOffset, final int dataSize) {
        ioSerialiser = source;
        this.parent = parent;
        this.fieldNameHashCode = fieldNameHashCode;
        this.fieldName = fieldName;
        this.dataType = dataType;
        this.fieldStart = fieldStart;
        this.dataStartOffset = dataStartOffset;
        this.dataSize = dataSize;
        this.fieldDataStart = fieldStart + dataStartOffset;

        if (this.parent != null /*&& !this.parent.getChildren().contains(this)*/) {
            this.parent.getChildren().add(this);
        }
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof FieldDescription)) {
            return false;
        }
        FieldDescription other = (FieldDescription) obj;
        if (this.getFieldNameHashCode() != other.getFieldNameHashCode()) {
            return false;
        }

        if (this.getDataType() != other.getDataType()) {
            return false;
        }

        return this.getFieldName().equals(other.getFieldName());
    }

    @Override
    public FieldDescription findChildField(final String fieldName) {
        return findChildField(fieldName.hashCode(), fieldName);
    }

    @Override
    public FieldDescription findChildField(final int fieldNameHashCode, final String fieldName) {
        for (int i = 0; i < children.size(); i++) { //NOSONAR
            final FieldDescription field = children.get(i);
            final String name = field.getFieldName();
            if (name == fieldName) { //NOSONAR //NOPMD early return if the same String object reference
                return field;
            }
            if (field.hashCode() == fieldNameHashCode && name.equals(fieldName)) {
                return field;
            }
        }
        return null;
    }

    @Override
    public List getChildren() {
        return children;
    }

    @Override
    public int getDataSize() {
        return dataSize;
    }

    public void setDataSize(final int size) {
        dataSize = size;
    }

    @Override
    public int getDataStartOffset() {
        return dataStartOffset;
    }

    @Override
    public int getDataStartPosition() {
        return fieldDataStart;
    }

    @Override
    public DataType getDataType() {
        return dataType;
    }

    @Override
    public String getFieldDescription() {
        return fieldDescription;
    }

    public void setFieldDescription(final String fieldDescription) {
        this.fieldDescription = fieldDescription;
    }

    @Override
    public String getFieldDirection() {
        return fieldDirection;
    }

    public void setFieldDirection(final String fieldDirection) {
        this.fieldDirection = fieldDirection;
    }

    @Override
    public List getFieldGroups() {
        return fieldGroups;
    }

    public void setFieldGroups(final List fieldGroups) {
        this.fieldGroups = fieldGroups;
    }

    @Override
    public String getFieldName() {
        return fieldName;
    }

    @Override
    public int getFieldNameHashCode() {
        return fieldNameHashCode;
    }

    @Override
    public int getFieldStart() {
        return fieldStart;
    }

    @Override
    public String getFieldUnit() {
        return fieldUnit;
    }

    public void setFieldUnit(final String fieldUnit) {
        this.fieldUnit = fieldUnit;
    }

    /**
     * @return raw ioSerialiser reference this field was retrieved with the position in the underlying IoBuffer at the to be read field
     * N.B. this is a safe convenience method and not performance optimised
     * @param overwriteType optional DataType as which the data should be interpreted
     */
    public Object data(DataType... overwriteType) {
        ioSerialiser.setQueryFieldName(fieldName, fieldDataStart);
        switch (overwriteType.length == 0 ? this.dataType : overwriteType[0]) {
        case START_MARKER:
        case END_MARKER:
            return null;
        case BOOL:
            return ioSerialiser.getBoolean();
        case BYTE:
            return ioSerialiser.getByte();
        case SHORT:
            return ioSerialiser.getShort();
        case INT:
            return ioSerialiser.getInt();
        case LONG:
            return ioSerialiser.getLong();
        case FLOAT:
            return ioSerialiser.getFloat();
        case DOUBLE:
            return ioSerialiser.getDouble();
        case CHAR:
            return ioSerialiser.getChar();
        case STRING:
            return ioSerialiser.getString();
        case BOOL_ARRAY:
            return ioSerialiser.getBooleanArray();
        case BYTE_ARRAY:
            return ioSerialiser.getByteArray();
        case SHORT_ARRAY:
            return ioSerialiser.getShortArray();
        case INT_ARRAY:
            return ioSerialiser.getIntArray();
        case LONG_ARRAY:
            return ioSerialiser.getLongArray();
        case FLOAT_ARRAY:
            return ioSerialiser.getFloatArray();
        case DOUBLE_ARRAY:
            return ioSerialiser.getDoubleArray();
        case CHAR_ARRAY:
            return ioSerialiser.getCharArray();
        case STRING_ARRAY:
            return ioSerialiser.getStringArray();
        case ENUM:
            return ioSerialiser.getEnum(null);
        case LIST:
            return ioSerialiser.getList(null);
        case MAP:
            return ioSerialiser.getMap(null);
        case QUEUE:
            return ioSerialiser.getQueue(null);
        case SET:
            return ioSerialiser.getSet(null);
        case COLLECTION:
            return ioSerialiser.getCollection(null);
        case OTHER:
            return ioSerialiser.getCustomData(null);
        default:
            throw new IllegalStateException("unknown dataType = " + dataType);
        }
    }

    /**
     * @return raw ioSerialiser reference this field was retrieved from w/o changing the position in the underlying IoBuffer
     */
    public IoSerialiser getIoSerialiser() {
        return ioSerialiser;
    }

    @Override
    public FieldDescription getParent() {
        return parent;
    }

    @Override
    public Class getType() {
        return dataType.getClassTypes().get(0);
    }

    @Override
    public int hashCode() {
        return fieldNameHashCode;
    }

    @Override
    public boolean isAnnotationPresent() {
        return fieldUnit != null || fieldDescription != null || fieldDirection != null || (fieldGroups != null && !fieldGroups.isEmpty());
    }

    @Override
    public void printFieldStructure() {
        if (parent != null) {
            LOGGER.atInfo().addArgument(parent).log("FielHeader structure (parent: {}):");
            printFieldStructure(this, 0);
        } else {
            LOGGER.atInfo().log("FielHeader structure (no parent):");
        }
        printFieldStructure(this, 0);
    }

    @Override
    public String toString() {
        return String.format("[fieldName=%s, fieldType=%s]", fieldName, dataType.getAsString());
    }

    protected static void printFieldStructure(final FieldDescription field, final int recursionLevel) {
        final String mspace = spaces((recursionLevel) *ClassUtils.getIndentationNumberOfSpace());
        LOGGER.atInfo().addArgument(mspace).addArgument(field.toString()).log("{}{}");
        if (field.isAnnotationPresent()) {
            LOGGER.atInfo().addArgument(mspace) //
                    .addArgument(field.getFieldUnit())
                    .addArgument(field.getFieldDescription())
                    .addArgument(field.getFieldDirection())
                    .addArgument(field.getFieldGroups())
                    .log("{}     ");
        }
        field.getChildren().forEach(f -> printFieldStructure(f, recursionLevel + 1));
    }

    private static String spaces(final int spaces) {
        return CharBuffer.allocate(spaces).toString().replace('\0', ' ');
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy