/*
* Copyright (C) 2009-2011 Mathias Doenitz
*
* 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 com.github.fge.grappa.matchers.base;
import com.github.fge.grappa.rules.Rule;
import com.google.common.collect.ImmutableList;
import com.github.fge.grappa.run.context.MatcherContext;
import com.github.fge.grappa.misc.ImmutableGraphNode;
import java.util.Objects;
/**
* Abstract base class of most regular {@link Matcher}s
*/
public abstract class AbstractMatcher
extends ImmutableGraphNode<Matcher>
implements Matcher, Cloneable
{
private String label;
protected AbstractMatcher(final String label)
{
this(new Rule[0], label);
}
protected AbstractMatcher(final Rule subRule, final String label)
{
this(new Rule[]{ Objects.requireNonNull(subRule, "subRule") },
label);
}
protected AbstractMatcher(final Rule[] subRules, final String label)
{
super(ImmutableList.copyOf(
toMatchers(Objects.requireNonNull(subRules))
)
);
this.label = label;
}
private static Matcher[] toMatchers(final Rule... subRules)
{
final Matcher[] matchers = new Matcher[subRules.length];
for (int i = 0; i < subRules.length; i++)
matchers[i] = (Matcher) subRules[i];
return matchers;
}
@Override
public String getLabel()
{
return label;
}
@Override
public boolean hasCustomLabel()
{
// this is the default implementation for single character matchers
// complex matchers override with a custom implementation
return true;
}
@Override
public final String toString()
{
return getLabel();
}
@Override
public final AbstractMatcher label(final String label)
{
if (Objects.equals(label, this.label))
return this;
final AbstractMatcher clone = createClone();
clone.label = label;
return clone;
}
// default implementation is to simply delegate to the context
@Override
public <V> MatcherContext<V> getSubContext(final MatcherContext<V> context)
{
return context.getSubContext(this);
}
// creates a shallow copy
private AbstractMatcher createClone()
{
try {
return (AbstractMatcher) clone();
} catch (CloneNotSupportedException e) {
throw new IllegalStateException(e);
}
}
}