/**
* Copyright 2011-2017 Asakusa Framework Team.
*
* 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.asakusafw.testdriver.rule;
import java.text.MessageFormat;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.asakusafw.testdriver.core.PropertyName;
/**
* Condition of property.
* @param <T> upper bound type of the property
* @since 0.2.0
*/
public class PropertyCondition<T> {
static final Logger LOG = LoggerFactory.getLogger(PropertyCondition.class);
private final PropertyName name;
private final Class<? extends T> type;
private final List<? extends ValuePredicate<? super T>> predicates;
/**
* Creates a new instance.
* @param name the property name
* @param type the property type
* @param predicates the value predicates
* @throws IllegalArgumentException if some parameters were {@code null}
*/
public PropertyCondition(
PropertyName name,
Class<? extends T> type,
List<? extends ValuePredicate<? super T>> predicates) {
if (name == null) {
throw new IllegalArgumentException("name must not be null"); //$NON-NLS-1$
}
if (type == null) {
throw new IllegalArgumentException("type must not be null"); //$NON-NLS-1$
}
if (predicates == null) {
throw new IllegalArgumentException("predicates must not be null"); //$NON-NLS-1$
}
if (predicates.isEmpty()) {
throw new IllegalArgumentException("predicates must not be empty"); //$NON-NLS-1$
}
this.name = name;
this.type = type;
this.predicates = predicates;
}
/**
* Returns the target property name.
* @return the target property name
*/
public PropertyName getPropertyName() {
return name;
}
/**
* Returns {@code true} iff exists a predicate accepts the pair.
* @param expected the expected value
* @param actual the actual value
* @return {@code true} iff exists a predicate accepts the pair
*/
public boolean accepts(Object expected, Object actual) {
T e = type.cast(expected);
T a = type.cast(actual);
for (ValuePredicate<? super T> predicate : predicates) {
try {
if (predicate.accepts(e, a)) {
return true;
}
} catch (IllegalArgumentException ex) {
// this means "ERROR" in ternary, continue checking rest conditions
if (LOG.isTraceEnabled()) {
LOG.trace(MessageFormat.format(
"Error occurred while evaluating predicate: " //$NON-NLS-1$
+ "predicate={0}, expected={1}, actual={2}", //$NON-NLS-1$
predicate,
e, a), ex);
}
}
}
return false;
}
/**
* Returns an expected value as readable text.
* @param expected the expected value (nullable)
* @param actual the actual value (nullable)
* @return readable text
*/
public String describeExpected(Object expected, Object actual) {
T e = type.cast(expected);
T a = type.cast(actual);
StringBuilder buf = new StringBuilder();
boolean sawDescription = false;
for (ValuePredicate<? super T> pred : predicates) {
String description = pred.describeExpected(e, a);
if (description == null) {
continue;
}
if (sawDescription) {
buf.append(Messages.getString("PropertyCondition.messageOrDescription")); //$NON-NLS-1$
}
sawDescription = true;
buf.append(MessageFormat.format(
Messages.getString("PropertyCondition.messageQuotedDescription"), //$NON-NLS-1$
description));
}
if (sawDescription) {
return buf.toString();
} else {
return Messages.getString("PropertyCondition.messageUnsupportedData"); //$NON-NLS-1$
}
}
}