/*******************************************************************************
* Copyright (c) 2005, 2007 committers of openArchitectureWare and others.
* 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:
* committers of openArchitectureWare - initial API and implementation
*******************************************************************************/
package org.eclipse.internal.xtend.type.baseimpl.types;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.internal.xtend.type.baseimpl.OperationImpl;
import org.eclipse.internal.xtend.type.baseimpl.PropertyImpl;
import org.eclipse.internal.xtend.util.StringHelper;
import org.eclipse.xtend.expression.TypeSystem;
import org.eclipse.xtend.typesystem.Feature;
import org.eclipse.xtend.typesystem.Type;
/**
* @author Sven Efftinge (http://www.efftinge.de)
* @author Arno Haase
*/
@SuppressWarnings("unchecked")
public class StringTypeImpl extends BuiltinBaseType {
final Log log = LogFactory.getLog(getClass());
public StringTypeImpl(final TypeSystem ts, final String name) {
super(ts, name);
}
public boolean isInstance(final Object o) {
return o instanceof String || o instanceof StringBuffer || o instanceof Character;
}
public Object newInstance() {
return "";
}
@Override
public Feature[] getContributedFeatures() {
return new Feature[] {
new PropertyImpl(this, "length", getTypeSystem().getIntegerType()) {
@Override
public String getDocumentation() {
return "the length of this string";
}
public Object get(final Object target) {
return new Long(target.toString().length());
}
},
new OperationImpl(this, "+", getTypeSystem().getStringType(), new Type[] { getTypeSystem()
.getObjectType() }) {
@Override
public String getDocumentation() {
return "concatenates two strings";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
return target.toString() + params[0];
}
},
new OperationImpl(this, "startsWith", getTypeSystem().getBooleanType(), new Type[] { getTypeSystem()
.getStringType() }) {
@Override
public String getDocumentation() {
return "Tests if this string starts with the specified prefix.";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
final String token = (String) params[0];
return new Boolean(target.toString().startsWith(token));
}
},
new OperationImpl(this, "contains", getTypeSystem().getBooleanType(), new Type[] { getTypeSystem()
.getStringType() }) {
@Override
public String getDocumentation() {
return "Tests if this string contains substring.";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
final String token = (String) params[0];
return new Boolean(target.toString().indexOf(token) >= 0);
}
},
new OperationImpl(this, "endsWith", getTypeSystem().getBooleanType(), new Type[] { getTypeSystem()
.getStringType() }) {
@Override
public String getDocumentation() {
return "Tests if this string ends with the specified prefix.";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
final String token = (String) params[0];
return new Boolean(target.toString().endsWith(token));
}
},
new OperationImpl(this, "subString", getTypeSystem().getStringType(), new Type[] {
getTypeSystem().getIntegerType(), getTypeSystem().getIntegerType() }) {
@Override
public String getDocumentation() {
return "Returns a new string that is a substring of this string.";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
final Number from = (Number) params[0];
final Number to = (Number) params[1];
return target.toString().substring(from.intValue(), to.intValue());
}
},
new OperationImpl(this, "toUpperCase", getTypeSystem().getStringType(), new Type[] {}) {
@Override
public String getDocumentation() {
return "Converts all of the characters in this String to upper"
+ " case using the rules of the default locale (from Java)";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
return target.toString().toUpperCase();
}
},
new OperationImpl(this, "toLowerCase", getTypeSystem().getStringType(), new Type[] {}) {
@Override
public String getDocumentation() {
return "Converts all of the characters in this String to lower"
+ " case using the rules of the default locale (from Java)";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
return target.toString().toLowerCase();
}
},
new OperationImpl(this, "toFirstUpper", getTypeSystem().getStringType(), new Type[] {}) {
@Override
public String getDocumentation() {
return "Converts the first character in this String to upper"
+ " case using the rules of the default locale (from Java)";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
return StringHelper.firstUpper(target.toString());
}
},
new OperationImpl(this, "toFirstLower", getTypeSystem().getStringType(), new Type[] {}) {
@Override
public String getDocumentation() {
return "Converts the first character in this String to lower"
+ " case using the rules of the default locale (from Java)";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
return StringHelper.firstLower(target.toString());
}
},
new OperationImpl(this, "toCharList", getTypeSystem().getListType(getTypeSystem().getStringType()),
new Type[] {}) {
@Override
public String getDocumentation() {
return "splits this String into a List[String] containing Strings of length 1";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
final String txt = target.toString();
final List<String> result = new ArrayList<String>();
final char[] chars = txt.toCharArray();
for (int i = 0; i < chars.length; i++) {
result.add(String.valueOf(chars[i]));
}
return result;
}
},
new OperationImpl(this, "replaceAll", getTypeSystem().getStringType(), new Type[] {
getTypeSystem().getStringType(), getTypeSystem().getStringType() }) {
@Override
public String getDocumentation() {
return "Replaces each substring of this string that matches the given "
+ "regular expression with the given replacement.";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
return target.toString().replaceAll(params[0].toString(), params[1].toString());
}
},
new OperationImpl(this, "replaceFirst", getTypeSystem().getStringType(), new Type[] {
getTypeSystem().getStringType(), getTypeSystem().getStringType() }) {
@Override
public String getDocumentation() {
return "Replaces the first substring of this string that matches the given"
+ " regular expression with the given replacement.";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
return target.toString().replaceFirst(params[0].toString(), params[1].toString());
}
},
new OperationImpl(this, "split", getTypeSystem().getListType(getTypeSystem().getStringType()),
new Type[] { getTypeSystem().getStringType() }) {
@Override
public String getDocumentation() {
return "Splits this string around matches of the given regular expression (from Java 1.4)";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
return new ArrayList<String>(Arrays.asList(target.toString().split(params[0].toString())));
}
},
new OperationImpl(this, "matches", getTypeSystem().getBooleanType(), new Type[] { getTypeSystem()
.getStringType() }) {
@Override
public String getDocumentation() {
return "Tells whether or not this string matches the given regular expression. (from Java 1.4)";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
return Boolean.valueOf(((String) target).matches((String) params[0]));
}
},
new OperationImpl(this, "trim", getTypeSystem().getStringType(), new Type[] {}) {
@Override
public String getDocumentation() {
return "Returns a copy of the string, with leading and trailing whitespace omitted. (from Java 1.4)";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
return ((String) target).trim();
}
},
new OperationImpl(this, "asInteger", getTypeSystem().getIntegerType(), new Type[] {}) {
@Override
public String getDocumentation() {
return "Returns an Integer object holding the value of the specified String (from Java 1.5)";
}
@Override
public Object evaluateInternal(final Object target, final Object[] params) {
try {
return new BigInteger((String) target);
}
catch (NumberFormatException nfe) {
log.error("'asInteger' on '" + target + "' returned null!");
return null;
}
}
}
};
}
@Override
public Set<Type> getSuperTypes() {
return Collections.singleton(getTypeSystem().getObjectType());
}
private String toString(final Object o) {
if (o == null)
return null;
if (isInstance(o))
return o.toString();
throw new IllegalArgumentException(o.getClass().getName() + " not supported");
}
@Override
public Object convert(final Object src, final Class targetType) {
final String s = toString(src);
if (targetType.isAssignableFrom(String.class))
return s;
else if (targetType.isAssignableFrom(Character.class) || targetType.isAssignableFrom(Character.TYPE)) {
if (s.length() == 1)
return new Character(s.charAt(0));
}
else if (targetType.isAssignableFrom(StringBuffer.class))
return new StringBuffer(s);
return super.convert(src, targetType);
}
}