001package jmri.jmrix.openlcb;
002
003import org.openlcb.implementations.BitProducerConsumer;
004
005import jmri.NamedBean;
006
007/**
008 * Helper functions used by multiple implementations but specific to JMRI to not go to the
009 * OpenLCB.jar.
010 *
011 * @author Balazs Racz Copyright (C) 2018
012 */
013
014public final class OlcbUtils {
015
016    private OlcbUtils(){
017        //class of constants and static methods.
018    }
019
020    public static final String PROPERTY_IS_AUTHORITATIVE = "IsAuthoritative";
021    public static final String PROPERTY_IS_PRODUCER = "IsProducer";
022    public static final String PROPERTY_IS_CONSUMER = "IsConsumer";
023    public static final String PROPERTY_QUERY_AT_STARTUP = "QueryAtStartup";
024    public static final String PROPERTY_LISTEN = "ListenStateMessages";
025    public static final String PROPERTY_LISTEN_INVALID = "ListenInvalidStateMessages";
026
027    /**
028     * Updates existing flags based on a boolean property.
029     *
030     * @param flags       previous value of flags
031     * @param parent      the parent JMRI object (OlcbTurnout or OlcbSensor)
032     * @param propertyKey string identifying the property
033     * @param flagValue   the bit to set/clear in the flag. If negative, then will get inverted
034     *                    from the found property value.
035     * @return new set of flags.
036     */
037    private static int updateBooleanProperty(int flags, NamedBean parent, String propertyKey, int
038            flagValue) {
039        Object propValue = parent.getProperty(propertyKey);
040        if (propValue == null) return flags;
041        if (!(propValue instanceof Boolean)) {
042            boolean v = Boolean.parseBoolean((String)propValue);
043            parent.setProperty(propertyKey, v);
044            propValue = v;
045        }
046        boolean prop = (Boolean)propValue;
047        if (flagValue < 0) {
048            prop = !prop;
049            flagValue = -flagValue;
050        }
051        if (prop) {
052            return flags | flagValue;
053        } else {
054            return flags & (~flagValue);
055        }
056    }
057
058    /**
059     * Checks the NamedBean properties and updates the BitProducerConsumer flags based on them.
060     *
061     * @param parent       NamedBean (OlcbSensor or OlcbTurnout) whose properties we'll check
062     * @param defaultFlags previous value of the flags.
063     * @return new value of flags. If not property is set on the object, then == defaultFlags.
064     */
065    static int overridePCFlagsFromProperties(NamedBean parent, int defaultFlags) {
066        int ret = defaultFlags;
067        ret = updateBooleanProperty(ret, parent, PROPERTY_IS_AUTHORITATIVE, -BitProducerConsumer
068                .SEND_UNKNOWN_EVENT_IDENTIFIED);
069        ret = updateBooleanProperty(ret, parent, PROPERTY_IS_PRODUCER, BitProducerConsumer
070                .IS_PRODUCER);
071        ret = updateBooleanProperty(ret, parent, PROPERTY_IS_CONSUMER, BitProducerConsumer
072                .IS_CONSUMER);
073        ret = updateBooleanProperty(ret, parent, PROPERTY_QUERY_AT_STARTUP, BitProducerConsumer
074                .QUERY_AT_STARTUP);
075        ret = updateBooleanProperty(ret, parent, PROPERTY_LISTEN, BitProducerConsumer
076                .LISTEN_EVENT_IDENTIFIED);
077        ret = updateBooleanProperty(ret, parent, PROPERTY_LISTEN_INVALID, BitProducerConsumer
078                .LISTEN_INVALID_STATE);
079        return ret;
080    }
081
082    /**
083     * Tests whether a given NamedBead is an OpenLCB implementation.
084     * @param b named bean object (e.g. Turnout object or Sensor object).
085     * @return true if it is an Olcb implementation.
086     */
087    static boolean isOlcbBean(NamedBean b) {
088        return b.getClass().getName().contains("Olcb");
089    }
090}