package com.thaiopensource.relaxng.pattern;
import com.thaiopensource.xml.util.Name;
import org.relaxng.datatype.Datatype;
import org.relaxng.datatype.DatatypeException;
import org.relaxng.datatype.ValidationContext;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* DataDerivType for a pattern which is a choice of values of the same datatype.
*/
class ValueDataDerivType extends DataDerivType {
private final Datatype dt;
private final Name dtName;
private PatternMemo noValue;
private Map<DatatypeValue, PatternMemo> valueMap;
ValueDataDerivType(Datatype dt, Name dtName) {
this.dt = dt;
this.dtName = dtName;
}
DataDerivType copy() {
return new ValueDataDerivType(dt, dtName);
}
PatternMemo dataDeriv(ValidatorPatternBuilder builder, Pattern p, String str, ValidationContext vc,
List<DataDerivFailure> fail) {
Object value = dt.createValue(str, vc);
if (value == null) {
if (noValue == null)
noValue = super.dataDeriv(builder, p, str, vc, fail);
else if (fail != null && noValue.isNotAllowed()) {
try {
dt.checkValid(str, vc);
}
catch (DatatypeException e) {
fail.add(new DataDerivFailure(dt, dtName, e));
}
}
return noValue;
}
else {
DatatypeValue dtv = new DatatypeValue(value, dt);
if (valueMap == null)
valueMap = new HashMap<DatatypeValue, PatternMemo>();
PatternMemo tem = valueMap.get(dtv);
if (tem == null) {
tem = super.dataDeriv(builder, p, str, vc, fail);
valueMap.put(dtv, tem);
}
else if (tem.isNotAllowed() && fail != null)
super.dataDeriv(builder, p, str, vc, fail);
return tem;
}
}
DataDerivType combine(DataDerivType ddt) {
if (ddt instanceof ValueDataDerivType) {
if (((ValueDataDerivType)ddt).dt == this.dt)
return this;
else
return InconsistentDataDerivType.getInstance();
}
else
return ddt.combine(this);
}
Datatype getDatatype() {
return dt;
}
}