com.fasterxml.jackson.databind.type.TypeParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
package com.fasterxml.jackson.databind.type;
import java.util.*;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.util.ClassUtil;
/**
* Simple recursive-descent parser for parsing canonical {@link JavaType}
* representations and constructing type instances.
*
* @author tatu
*/
public class TypeParser
implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
protected final TypeFactory _factory;
public TypeParser(TypeFactory f) {
_factory = f;
}
public JavaType parse(String canonical)
throws IllegalArgumentException
{
canonical = canonical.trim();
MyTokenizer tokens = new MyTokenizer(canonical);
JavaType type = parseType(tokens);
// must be end, now
if (tokens.hasMoreTokens()) {
throw _problem(tokens, "Unexpected tokens after complete type");
}
return type;
}
protected JavaType parseType(MyTokenizer tokens)
throws IllegalArgumentException
{
if (!tokens.hasMoreTokens()) {
throw _problem(tokens, "Unexpected end-of-string");
}
Class base = findClass(tokens.nextToken(), tokens);
// either end (ok, non generic type), or generics
if (tokens.hasMoreTokens()) {
String token = tokens.nextToken();
if ("<".equals(token)) {
return _factory._fromParameterizedClass(base, parseTypes(tokens));
}
// can be comma that separates types, or closing '>'
tokens.pushBack(token);
}
return _factory._fromClass(base, null);
}
protected List parseTypes(MyTokenizer tokens)
throws IllegalArgumentException
{
ArrayList types = new ArrayList();
while (tokens.hasMoreTokens()) {
types.add(parseType(tokens));
if (!tokens.hasMoreTokens()) break;
String token = tokens.nextToken();
if (">".equals(token)) return types;
if (!",".equals(token)) {
throw _problem(tokens, "Unexpected token '"+token+"', expected ',' or '>')");
}
}
throw _problem(tokens, "Unexpected end-of-string");
}
protected Class findClass(String className, MyTokenizer tokens)
{
try {
return ClassUtil.findClass(className);
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw _problem(tokens, "Can not locate class '"+className+"', problem: "+e.getMessage());
}
}
protected IllegalArgumentException _problem(MyTokenizer tokens, String msg)
{
return new IllegalArgumentException("Failed to parse type '"+tokens.getAllInput()
+"' (remaining: '"+tokens.getRemainingInput()+"'): "+msg);
}
final static class MyTokenizer
extends StringTokenizer
{
protected final String _input;
protected int _index;
protected String _pushbackToken;
public MyTokenizer(String str) {
super(str, "<,>", true);
_input = str;
}
@Override
public boolean hasMoreTokens() {
return (_pushbackToken != null) || super.hasMoreTokens();
}
@Override
public String nextToken() {
String token;
if (_pushbackToken != null) {
token = _pushbackToken;
_pushbackToken = null;
} else {
token = super.nextToken();
}
_index += token.length();
return token;
}
public void pushBack(String token) {
_pushbackToken = token;
_index -= token.length();
}
public String getAllInput() { return _input; }
public String getUsedInput() { return _input.substring(0, _index); }
public String getRemainingInput() { return _input.substring(_index); }
}
}