applyFirstGroup) {
final Pattern patternForMatcher = compile(checkNotNull(pattern, "pattern"), DOTALL);
checkNotNull(applyFirstGroup, "applyFirstGroup");
return new Decoder() {
@Override
public Object decode(String methodKey, Reader reader, Type type) throws Throwable {
Matcher matcher = patternForMatcher.matcher(Decoders.toString(reader));
if (matcher.find()) {
return applyFirstGroup.apply(matcher.group(1));
}
return null;
}
@Override public String toString() {
return format("decode groups from %s into %s", patternForMatcher, applyFirstGroup);
}
};
}
/**
* shortcut for {@link Decoders#transformFirstGroup(String, ApplyFirstGroup)} when
* {@code String} is the type you are decoding into.
*
*
* Ex. to pull the first interesting element from an xml response:
*
*
* decodeFirstDirPoolID = firstGroup("<DirPoolID[ˆ>]*>([ˆ<]+)</DirPoolID>");
*
*/
public static Decoder firstGroup(String pattern) {
return transformFirstGroup(pattern, IDENTITY);
}
/**
* On the each find the first match group is applied to
* {@code applyFirstGroup} and added to the list returned. If no matches are
* found, the response is an empty list;
*
* Ex. to pull a list zones constructed from http paths starting with
* {@code /Rest/Zone/}:
*
*
* decodeListOfZones = transformEachFirstGroup("/REST/Zone/([ˆ/]+)/", ToZone.INSTANCE);
*
*/
public static Decoder transformEachFirstGroup(String pattern, final ApplyFirstGroup applyFirstGroup) {
final Pattern patternForMatcher = compile(checkNotNull(pattern, "pattern"), DOTALL);
checkNotNull(applyFirstGroup, "applyFirstGroup");
return new Decoder() {
@Override
public List decode(String methodKey, Reader reader, Type type) throws Throwable {
Matcher matcher = patternForMatcher.matcher(Decoders.toString(reader));
List result = new ArrayList();
while (matcher.find()) {
result.add(applyFirstGroup.apply(matcher.group(1)));
}
return result;
}
@Override public String toString() {
return format("decode %s into list elements, where each group(1) is transformed with %s",
patternForMatcher, applyFirstGroup);
}
};
}
/**
* shortcut for {@link Decoders#transformEachFirstGroup(String, ApplyFirstGroup)}
* when {@code List} is the type you are decoding into.
*
* Ex. to pull a list zones names, which are http paths starting with
* {@code /Rest/Zone/}:
*
*
* decodeListOfZonesNames = eachFirstGroup("/REST/Zone/([ˆ/]+)/");
*
*/
public static Decoder eachFirstGroup(String pattern) {
return transformEachFirstGroup(pattern, IDENTITY);
}
private static String toString(Reader reader) throws Throwable {
return TO_STRING.decode(null, reader, null).toString();
}
private static final Decoder TO_STRING = new ToStringDecoder();
private static final ApplyFirstGroup IDENTITY = new ApplyFirstGroup() {
@Override public String apply(String firstGroup) {
return firstGroup;
}
};
}