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

org.phoebus.applications.alarm.model.json.JsonModelReader Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2018-2021 Oak Ridge National Laboratory.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package org.phoebus.applications.alarm.model.json;

import static org.phoebus.applications.alarm.AlarmSystem.logger;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.phoebus.applications.alarm.client.AlarmClientLeaf;
import org.phoebus.applications.alarm.client.AlarmClientNode;
import org.phoebus.applications.alarm.client.ClientState;
import org.phoebus.applications.alarm.model.AlarmTreeItem;
import org.phoebus.applications.alarm.model.AlarmTreeLeaf;
import org.phoebus.applications.alarm.model.BasicState;
import org.phoebus.applications.alarm.model.SeverityLevel;
import org.phoebus.applications.alarm.model.TitleDetail;
import org.phoebus.applications.alarm.model.TitleDetailDelay;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;

/** Read alarm model from JSON
 *  @author Kay Kasemir
 */
@SuppressWarnings("nls")
public class JsonModelReader
{
    // The following use 'Object' for the json node instead of actual
    // JsonNode to keep Jackson specifics within this package.
    // Later updates of the JsonModelReader/Writer will not affect code
    // that calls them.

    /** Parse JSON text
     *  @param json_text JSON text
     *  @return JSON object
     *  @throws Exception on error
     */
    public static Object parseJsonText(final String json_text) throws Exception
    {
        try
        (
            final JsonParser jp = JsonModelWriter.mapper.getFactory().createParser(json_text);
        )
        {
            return JsonModelWriter.mapper.readTree(jp);
        }
    }

    /** Is this the configuration or alarm state for a leaf?
     *  @param json JSON returned by {@link #parseJsonText(String)}
     *  @return true for {@link AlarmTreeLeaf}, false for {@link AlarmClientNode}
     */
    public static boolean isLeafConfigOrState(final Object json)
    {
        final JsonNode actual = (JsonNode) json;
        // Leaf config contains description
        // Leaf alarm state contains detail of AlarmState
        return actual.get(JsonTags.DESCRIPTION) != null  ||  actual.get(JsonTags.CURRENT_SEVERITY) != null;
    }

    /** Is this a configuration or state message?
     *  @param json JSON returned by {@link #parseJsonText(String)}
     *  @return true for {@link AlarmTreeLeaf}, false for {@link AlarmClientNode}
     */
    public static boolean isStateUpdate(final Object json)
    {
        final JsonNode actual = (JsonNode) json;
        // State updates contain SEVERITY
        return actual.get(JsonTags.SEVERITY) != null;
    }

    /** Update configuration of alarm tree item
     *  @param node {@link AlarmTreeItem}
     *  @param json JSON with settings for the item
     *  @return true if configuration changed, false if there was nothing to update
     */
    public static boolean updateAlarmItemConfig(final AlarmTreeItem node, final Object json)
    {
        final JsonNode actual = (JsonNode) json;
        boolean changed = updateAlarmNodeConfig(node, actual);
        if (node instanceof AlarmTreeLeaf)
            changed |= updateAlarmLeafConfig((AlarmTreeLeaf) node, actual);
        return changed;
    }

    /** Update general {@link AlarmTreeItem} settings */
    private static boolean updateAlarmNodeConfig(final AlarmTreeItem node, final JsonNode json)
    {
        boolean changed = false;

        JsonNode jn = json.get(JsonTags.GUIDANCE);
        if (jn == null)
            changed |= node.setGuidance(Collections.emptyList());
        else
            changed |= node.setGuidance(parseTitleDetail(jn));

        jn = json.get(JsonTags.DISPLAYS);
        if (jn == null)
            changed |= node.setDisplays(Collections.emptyList());
        else
            changed |= node.setDisplays(patchDisplays(parseTitleDetail(jn)));

        jn = json.get(JsonTags.COMMANDS);
        if (jn == null)
            changed |= node.setCommands(Collections.emptyList());
        else
            changed |= node.setCommands(parseTitleDetail(jn));

        jn = json.get(JsonTags.ACTIONS);
        if (jn == null)
            changed |= node.setActions(Collections.emptyList());
        else
            changed |= node.setActions(parseTitleDetailDelay(jn));

        return changed;
    }

    /** Patch legacy display links
     *
     *  

Remove "opi:" prefix from web links. * Used to be necessary to force display runtime for http://...opi, * but file extension now sufficient. * * @param displays Original displays * @return Displays where entries may be replaced */ private static List patchDisplays(final List displays) { final int N = displays.size(); for (int i=0; i parseTitleDetail(final JsonNode array) { final List entries = new ArrayList<>(array.size()); for (int i=0; i parseTitleDetailDelay(final JsonNode array) { final List entries = new ArrayList<>(array.size()); for (int i=0; itrue if in maintenance mode */ public static boolean isMaintenanceMode(final Object json) { final JsonNode actual = (JsonNode) json; JsonNode jn = actual.get(JsonTags.MODE); if (jn != null) return JsonTags.MAINTENANCE.equals(jn.asText()); return false; } /** Check for 'notify' mode indicator, * included in alarm state updates * @param json JSON * @return true if in disable_notify mode */ public static boolean isDisableNotify(final Object json) { final JsonNode actual = (JsonNode) json; JsonNode jn = actual.get(JsonTags.NOTIFY); return jn == null ? false : !jn.asBoolean(); } /** Check for config 'delete' info message * @param json JSON * @return true if in disable_notify mode */ public static boolean isConfigDeletion(final Object json) { final JsonNode actual = (JsonNode) json; final JsonNode jn = actual.get(JsonTags.DELETE); return jn != null; } /** Update alarm state from received JSON * @param node Node to update * @param json JSON with state information * @return Was that a change? */ public static boolean updateAlarmState(final AlarmTreeItem node, final Object json) { final JsonNode actual = (JsonNode) json; if (node instanceof AlarmClientLeaf) return updateAlarmLeafState((AlarmClientLeaf) node, actual); if (node instanceof AlarmClientNode) return updateAlarmNodeState((AlarmClientNode) node, actual); return false; } /** @param _json JSon that might contain {@link ClientState} * @return {@link ClientState} or null */ public static ClientState parseClientState(final Object _json) { final JsonNode json = (JsonNode) _json; SeverityLevel severity = SeverityLevel.UNDEFINED; String message = ""; String value = ""; Instant time = null; SeverityLevel current_severity = SeverityLevel.UNDEFINED; String current_message = ""; JsonNode jn = json.get(JsonTags.SEVERITY); if (jn == null) return null; severity = SeverityLevel.valueOf(jn.asText()); jn = json.get(JsonTags.LATCH); final boolean latch = jn != null && Boolean.parseBoolean(jn.asText()); jn = json.get(JsonTags.MESSAGE); if (jn == null) return null; message = jn.asText(); jn = json.get(JsonTags.VALUE); if (jn == null) return null; value = jn.asText(); jn = json.get(JsonTags.CURRENT_SEVERITY); if (jn == null) return null; current_severity = SeverityLevel.valueOf(jn.asText()); jn = json.get(JsonTags.CURRENT_MESSAGE); if (jn == null) return null; current_message = jn.asText(); jn = json.get(JsonTags.TIME); if (jn == null) return null; long secs = 0, nano = 0; JsonNode sub = jn.get(JsonTags.SECONDS); if (sub != null) secs = sub.asLong(); sub = jn.get(JsonTags.NANO); if (sub != null) nano = sub.asLong(); time = Instant.ofEpochSecond(secs, nano); return new ClientState(severity, message, value, time, current_severity, current_message, latch); } /** @param node Node to update from json * @param json Json that might contain {@link ClientState} * @return true if this changed the alarm state of the node */ private static boolean updateAlarmLeafState(final AlarmClientLeaf node, final JsonNode json) { final ClientState state = parseClientState(json); return (state != null) && node.setState(state); } private static boolean updateAlarmNodeState(final AlarmClientNode node, final JsonNode json) { SeverityLevel severity = SeverityLevel.UNDEFINED; JsonNode jn = json.get(JsonTags.SEVERITY); if (jn == null) return false; severity = SeverityLevel.valueOf(jn.asText()); // Compare alarm state with node's current state if (node.getState().severity == severity) return false; final BasicState state = new BasicState(severity); node.setState(state); return true; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy