dk.dma.msiproxy.model.MessageFilter.java Source code

Java tutorial

Introduction

Here is the source code for dk.dma.msiproxy.model.MessageFilter.java

Source

/* Copyright (c) 2011 Danish Maritime Authority
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */
package dk.dma.msiproxy.model;

import dk.dma.msiproxy.model.msi.Area;
import dk.dma.msiproxy.model.msi.Category;
import dk.dma.msiproxy.model.msi.Message;
import dk.dma.msiproxy.model.msi.SeriesIdType;
import dk.dma.msiproxy.model.msi.Type;
import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * Used for filtering messages
 */
public class MessageFilter {

    boolean detailed = true;
    String lang;
    Set<SeriesIdType> mainTypes = new HashSet<>();
    Set<Type> types = new HashSet<>();
    Integer areaId;
    Integer categoryId;

    /**
     * Returns whether this filter is empty or not
     * @return whether this filter is empty or not
     */
    public boolean isEmpty() {
        return StringUtils.isBlank(lang) && mainTypes.isEmpty() && types.isEmpty() && areaId == null
                && categoryId == null;
    }

    /**
     * Returns a key that uniquely defines the filter
     * @return a key that uniquely defines the filter
     */
    public String getKey() {
        // Need to make sure that the types are enlisted in a deterministic order
        List<SeriesIdType> mainTypes = new ArrayList<>(this.mainTypes);
        Collections.sort(mainTypes);
        List<Type> types = new ArrayList<>(this.types);
        Collections.sort(types);
        return String.format("%s_%b_%s_%s_%s_%s", StringUtils.defaultString(lang), detailed,
                mainTypes.stream().map(Enum::toString).collect(Collectors.joining("-")),
                types.stream().map(Enum::toString).collect(Collectors.joining("-")),
                areaId == null ? "" : areaId.toString(), categoryId == null ? "" : categoryId.toString());
    }

    /**
     * Filters the list of messages according to the current filter
     * @param messages the list of messages to filter
     * @return the filtered list of messages
     */
    public List<Message> filter(List<Message> messages) {
        if (messages == null || isEmpty()) {
            return messages;
        }

        List<Message> result = new CopyOnWriteArrayList<>();
        result.addAll(messages.stream().filter(this::filterMessage).map(msg -> new Message(msg, this))
                .filter(msg -> msg.getDescs() != null && msg.getDescs().size() > 0).collect(Collectors.toList()));
        return result;
    }

    /**
     * Returns if the message is included in the filter or not
     * @param msg the message to check
     * @return if the message is included in the filter or not
     */
    private boolean filterMessage(Message msg) {

        // Filter on main type
        boolean included = mainTypes.isEmpty() || mainTypes.contains(msg.getSeriesIdentifier().getMainType());

        // Filter on type
        included &= types.isEmpty() || types.contains(msg.getType());

        // Filter on area
        if (areaId != null) {
            boolean found = false;
            for (Area area = msg.getArea(); !found && area != null; area = area.getParent()) {
                found = Objects.equals(area.getId(), areaId);
            }
            included &= found;
        }

        // Filter on category
        if (categoryId != null) {
            boolean found = false;
            if (msg.getCategories() != null) {
                for (Iterator<Category> it = msg.getCategories().iterator(); !found && it.hasNext();) {
                    Category cat = it.next();
                    for (Category category = cat; !found && category != null; category = category.getParent()) {
                        found = Objects.equals(category.getId(), categoryId);
                    }
                }
            }
            included &= found;
        }

        return included;
    }

    /**
     * Sets the language to filter by
     * @param lang the language to filter by
     * @return the updated message filter
     */
    public MessageFilter lang(String lang) {
        this.lang = lang;
        return this;
    }

    /**
     * Sets whether to include detailed data or not
     * @param detailed whether to include detailed data or not
     * @return the updated message filter
     */
    public MessageFilter detailed(boolean detailed) {
        this.detailed = detailed;
        return this;
    }

    /**
     * Sets the types to filter by. The type may either be
     * one of the main types, "MSI" or "NM", or one of the sub-types,
     * "PERMANENT_NOTICE", "TEMPORARY_NOTICE", "PRELIMINARY_NOTICE", "MISCELLANEOUS_NOTICE",
     * "COASTAL_WARNING", "SUBAREA_WARNING", "NAVAREA_WARNING", "LOCAL_WARNING".
     *
     * @param types the types to filter by
     * @return the updated message filter
     */
    public MessageFilter types(String... types) {
        if (types != null && types.length > 0) {
            Arrays.asList(types).forEach(type -> {
                if (type.equals("MSI") || type.equals("NM")) {
                    this.mainTypes.add(SeriesIdType.valueOf(type));
                } else if (StringUtils.isNotBlank(type)) {
                    this.types.add(Type.valueOf(type));
                }
            });
        }
        return this;
    }

    /**
     * Sets the area ID to filter by
     * @param areaId the area to filter by
     * @return the updated message filter
     */
    public MessageFilter area(Integer areaId) {
        this.areaId = areaId;
        return this;
    }

    /**
     * Sets the category ID to filter by
     * @param categoryId the category to filter by
     * @return the updated message filter
     */
    public MessageFilter category(Integer categoryId) {
        this.categoryId = categoryId;
        return this;
    }

    public boolean isDetailed() {
        return detailed;
    }

    public String getLang() {
        return lang;
    }

    public Set<SeriesIdType> getMainTypes() {
        return mainTypes;
    }

    public Set<Type> getTypes() {
        return types;
    }

    public Integer getAreaId() {
        return areaId;
    }
}