/*******************************************************************************
* Copyright (c) 2008 Hallvard Traetteberg.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Hallvard Traetteberg - initial API and implementation
******************************************************************************/
package org.eclipse.e4.tm.stringconverters;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.e4.tm.stringconverter.AbstractStringConverter;
import org.eclipse.e4.tm.stringconverter.StringConverterContext;
public class SimpleObjectStringConverter extends AbstractStringConverter {
// Support this kind of syntax: layout="<class>{<propertyClass>:<propertyName>=<valueString>}"
private char classNamePropertyNameSeparator = ':';
private char propertyNameValueSeparator = '=';
private char propertyDelimiter = ';';
private String separator(char separator) {
return "\\s*" + "\\" + separator + "\\s*";
}
private String nameSyntax = "\\w+";
private String classNameSyntax = nameSyntax + "(?:\\." + nameSyntax + ")*";
private String valueSyntax = "[^" + propertyDelimiter + "]*";
private String propertySyntax = "(?:(" + classNameSyntax + ")" + separator(classNamePropertyNameSeparator) + ")?(" + nameSyntax + ")" + separator(propertyNameValueSeparator) + "(" + valueSyntax + ")" + separator(propertyDelimiter);
private Pattern propertyPattern = Pattern.compile(propertySyntax);
public <T> T convert(String source, Class<T> klass, StringConverterContext context) {
int pos1 = source.indexOf("{"), pos2 = source.lastIndexOf("}");
if (pos1 < 0 || pos2 < 0 || pos2 < source.length() - 1) {
return null;
}
Class<?> resultClass = convertThrowing(source.substring(0, pos1).trim(), Class.class, context);
T result = null;
if (klass.isAssignableFrom(resultClass)) {
try {
Object o = resultClass.newInstance();
result = (klass.isInstance(o) ? (T)o : null);
} catch (Exception e1) {
}
}
if (result == null) {
return null;
}
String propertiesString = source.substring(pos1 + 1, pos2);
Matcher matcher = propertyPattern.matcher(propertiesString);
int start = 0;
while (matcher.find(start)) {
if (matcher.start() != start) {
return null;
}
int count = matcher.groupCount();
if (count == 0) {
return null;
}
String valueClassName = (count > 2 ? matcher.group(1) : null);
String propertyName = matcher.group(valueClassName != null ? 2 : 1);
String valueString = matcher.group(valueClassName != null ? 3 : 2);
try {
Class<?> valueClass = context.convert(valueClassName, Class.class);
Object value = context.convert(valueString, valueClass);
context.setProperty(result, propertyName, value);
} catch (Exception e) {
throwConversionException(source, klass, e);
}
start = matcher.end();
}
return (start < propertiesString.length() ? null : result);
}
}