de.sayayi.lib.protocol.spi.AbstractProtocol Maven / Gradle / Ivy
/*
* Copyright 2019 Jeroen Gremmen
*
* 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 de.sayayi.lib.protocol.spi;
import de.sayayi.lib.protocol.Level;
import de.sayayi.lib.protocol.Protocol;
import de.sayayi.lib.protocol.Protocol.ProtocolMessageBuilder;
import de.sayayi.lib.protocol.ProtocolEntry;
import de.sayayi.lib.protocol.ProtocolFactory;
import de.sayayi.lib.protocol.ProtocolFormatter;
import de.sayayi.lib.protocol.ProtocolGroup;
import de.sayayi.lib.protocol.ProtocolIterator.DepthEntry;
import de.sayayi.lib.protocol.ProtocolIterator.GroupEndEntry;
import de.sayayi.lib.protocol.ProtocolIterator.GroupStartEntry;
import de.sayayi.lib.protocol.ProtocolIterator.MessageEntry;
import de.sayayi.lib.protocol.ProtocolIterator.ProtocolEnd;
import de.sayayi.lib.protocol.ProtocolIterator.ProtocolStart;
import de.sayayi.lib.protocol.TagSelector;
import de.sayayi.lib.protocol.matcher.MessageMatcher;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.val;
import lombok.var;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import static java.util.Spliterator.DISTINCT;
import static java.util.Spliterator.NONNULL;
import static java.util.Spliterator.ORDERED;
import static java.util.Spliterator.SORTED;
/**
* @param internal message object type
*
* @author Jeroen Gremmen
*/
@EqualsAndHashCode(onlyExplicitlyIncluded = true, doNotUseGetters = true, callSuper = false)
abstract class AbstractProtocol>
implements Protocol, InternalProtocolQueryable
{
private static final AtomicInteger PROTOCOL_ID = new AtomicInteger(0);
@EqualsAndHashCode.Include
@Getter private final int id;
@Getter final @NotNull ProtocolFactory factory;
final @NotNull ParameterMap parameterMap;
final @NotNull List> entries;
final @NotNull Map> tagPropagationMap;
protected AbstractProtocol(@NotNull ProtocolFactory factory, ParameterMap parentParameterMap)
{
this.factory = factory;
id = PROTOCOL_ID.incrementAndGet();
parameterMap = new ParameterMap(parentParameterMap);
entries = new ArrayList<>(8);
tagPropagationMap = new HashMap<>(8);
}
protected @NotNull Set getPropagatedTags(@NotNull Set tags)
{
if (tagPropagationMap.isEmpty())
return tags;
val collectedPropagatedTagDefs = new TreeSet<>(tags);
for(val tagPropagation: tagPropagationMap.entrySet())
if (tagPropagation.getKey().match(collectedPropagatedTagDefs))
collectedPropagatedTagDefs.addAll(tagPropagation.getValue());
return collectedPropagatedTagDefs;
}
public abstract @NotNull B add(@NotNull Level level);
@Override
public boolean matches0(@NotNull Level levelLimit, @NotNull MessageMatcher matcher)
{
for(val entry: entries)
if (entry.matches0(levelLimit, matcher))
return true;
return false;
}
@NotNull List> getEntries(@NotNull Level levelLimit,
@NotNull MessageMatcher matcher)
{
val filteredEntries = new ArrayList>();
for(val entry: entries)
if (entry.matches0(levelLimit, matcher))
{
if (entry instanceof InternalProtocolEntry.Group)
{
filteredEntries.add(ProtocolGroupEntryAdapter.from(levelLimit,
(InternalProtocolEntry.Group)entry));
}
else
{
filteredEntries.add(ProtocolMessageEntryAdapter.from(levelLimit,
(InternalProtocolEntry.Message)entry));
}
}
return filteredEntries;
}
@Override
public int getVisibleEntryCount0(@NotNull Level levelLimit, @NotNull MessageMatcher matcher)
{
var count = 0;
for(val entry: entries)
count += entry.getVisibleEntryCount0(levelLimit, matcher);
return count;
}
@Override
public @NotNull Optional> getGroupByName(@NotNull String name)
{
for(final Iterator> groupIterator = groupIterator(); groupIterator.hasNext();)
{
val result = groupIterator.next().getGroupByName(name);
if (result.isPresent())
return result;
}
return Optional.empty();
}
@Override
public void forEachGroupByRegex(@NotNull String regex, @NotNull Consumer> action) {
groupIterator().forEachRemaining(group -> group.forEachGroupByRegex(regex, action));
}
@Override
public @NotNull ProtocolGroup createGroup()
{
@SuppressWarnings("unchecked")
val group = new ProtocolGroupImpl<>((AbstractProtocol>)this);
entries.add(group);
return group;
}
@Override
public @NotNull Spliterator> spliterator(@NotNull MessageMatcher matcher) {
return new ProtocolSpliterator<>(iterator(matcher));
}
@Override
public @NotNull Iterator> groupIterator() {
return new GroupIterator();
}
@Override
public @NotNull Spliterator> groupSpliterator()
{
return Spliterators.spliterator(groupIterator(), entries.size(),
DISTINCT | ORDERED | SORTED | NONNULL);
}
@Override
public R format(@NotNull ProtocolFormatter formatter, @NotNull MessageMatcher matcher)
{
// initialize formatter
formatter.init(factory, matcher,
countGroupDepth() + (isProtocolGroup() ? 1 : 0));
iterator(matcher).forEachRemaining(entry -> {
if (entry instanceof MessageEntry)
formatter.message((MessageEntry)entry);
else if (entry instanceof GroupStartEntry)
formatter.groupStart((GroupStartEntry)entry);
else if (entry instanceof GroupEndEntry)
formatter.groupEnd((GroupEndEntry)entry);
else if (entry instanceof ProtocolStart)
formatter.protocolStart();
else if (entry instanceof ProtocolEnd)
formatter.protocolEnd();
});
return formatter.getResult();
}
int countGroupDepth()
{
var depth = 0;
for(val entry: entries)
if (entry instanceof ProtocolGroupImpl)
depth = Math.max(depth, 1 + ((ProtocolGroupImpl)entry).countGroupDepth());
return depth;
}
/**
* @since 0.7.0
*/
protected final class GroupIterator implements Iterator>
{
private final Iterator> iterator;
private ProtocolGroup next;
private GroupIterator()
{
iterator = entries.iterator();
findNext();
}
private void findNext()
{
while(iterator.hasNext())
{
val entry = iterator.next();
if (entry instanceof ProtocolGroup)
{
//noinspection unchecked
next = (ProtocolGroup)entry;
return;
}
}
next = null;
}
@Override
public boolean hasNext() {
return next != null;
}
@Override
public ProtocolGroup next()
{
if (!hasNext())
throw new NoSuchElementException();
val nextGroup = next;
findNext();
return nextGroup;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy