ArduinoMsgFilter.java

/*******************************************************************************
 * jArduino: Arduino C++ Code Generation From Java
 * Copyright 2020 Tony Washer
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package net.sourceforge.jarduino.message;

import java.util.HashMap;
import java.util.Map;

/**
 * Message selection.
 */
public class ArduinoMsgFilter {
    /**
     * Parse message indication.
     */
    private static final Integer ZERO = 0;

    /**
     * Parse message indication.
     */
    public static final int PARSEMSG = 1;

    /**
     * Build message indication.
     */
    public static final int BUILDMSG = 2;

    /**
     * The map of messageId to output selection.
     */
    private final Map<String, Integer> theSelection;

    /**
     * The public fields indication.
     */
    private boolean pubFields;

    /**
     * Constructor.
     */
    public ArduinoMsgFilter() {
        theSelection = new HashMap<>();
    }

    /**
     * Obtain the number of messages.
     * @return the number of messages
     */
    public int size() {
        return theSelection.size();
    }

    /**
     * Is the selection empty?
     * @return true/false
     */
    public boolean isEmpty() {
        return theSelection.isEmpty();
    }

    /**
     * Are fields public?
     * @return true/false
     */
    public boolean publicFields() {
        return pubFields;
    }

    /**
     * toggle public fields.
     */
    public void togglePublicFields() {
        pubFields = !pubFields;
    }

    /**
     * Does the map have any selected entries.
     * @return true/false
     */
    public boolean hasSelected() {
        /* Loop through the map */
        for (Integer myValue : theSelection.values()) {
            if (!ZERO.equals(myValue)) {
                return true;
            }
        }

        /* No selected entries */
        return false;
    }

    /**
     * Is the message selected?
     * @param pId the messageId
     * @return true/false
     */
    public boolean isSelected(final String pId) {
        final Integer myState = theSelection.get(pId);
        return myState != null && !ZERO.equals(myState);
    }

    /**
     * Is the message selected for parse?
     * @param pId the messageId
     * @return true/false
     */
    public boolean isParsed(final String pId) {
        final Integer myState = theSelection.get(pId);
        return myState != null && !ZERO.equals(myState & PARSEMSG);
    }

    /**
     * Is the message selected for build?
     * @param pId the messageId
     * @return true/false
     */
    public boolean isBuilt(final String pId) {
        final Integer myState = theSelection.get(pId);
        return myState != null && !ZERO.equals(myState & BUILDMSG);
    }

    /**
     * Toggle the flag for the message.
     * @param pId the messageId
     * @param pFlag the flag
     */
    public void toggleFlag(final String pId,
                           final int pFlag) {
        /* Calculate the new state */
        Integer myState = theSelection.computeIfAbsent(pId, i -> ZERO);
        myState ^= pFlag;

        /* Remove or update the state */
        if (ZERO.equals(myState)) {
            removeMessage(pId);
        } else {
            theSelection.put(pId, myState);
        }
    }

    /**
     * Select message.
     * @param pId the messageId
     */
    public void selectMessage(final String pId) {
        theSelection.put(pId, PARSEMSG | BUILDMSG);
    }

    /**
     * Remove message.
     * @param pId the messageId
     */
    public void removeMessage(final String pId) {
        theSelection.remove(pId);
    }

    /**
     * Reset the selection for a new object.
     * @param pObject the object
     */
    public void resetSelection(final ArduinoNamedObject pObject) {
        if (pObject instanceof ArduinoSystem) {
            resetSelection((ArduinoSystem) pObject);
        }
        if (pObject instanceof ArduinoNode) {
            resetSelection((ArduinoNode) pObject);
        }
    }

    /**
     * Reset the selection for a new system.
     * @param pSystem the system
     */
    public void resetSelection(final ArduinoSystem pSystem) {
        /* Remove the existing selection */
        theSelection.clear();

        /* Loop through the messages */
        for (ArduinoMessage myMessage : pSystem.getMessages()) {
            /* Add all messages by default */
            theSelection.put(myMessage.getId(), PARSEMSG | BUILDMSG);
        }
    }

    /**
     * Match the selection to a node.
     * @param pNode the node
     */
    public void resetSelection(final ArduinoNode pNode) {
        /* Remove the existing selection */
        theSelection.clear();

        /* Loop through the messages */
        for (ArduinoMessage myMessage : pNode.getOwner().getMessages()) {
            /* Determine if we send the message */
            int myValue = pNode.getMessages().contains(myMessage) ? BUILDMSG : ZERO;

            /* Determine if we receive the message */
            if (pNode.receivesMessage(myMessage)) {
                myValue |= PARSEMSG;
            }

            /* If we should handle the message */
            if (!ZERO.equals(myValue)) {
                /* Add to the selection */
                theSelection.put(myMessage.getId(), myValue);
            }
        }
    }
}