/*
* JBoss by Red Hat
* Copyright 2006-2009, Red Hat Middleware, LLC, and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.ide.eclipse.freemarker.model.interpolation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.source.ISourceViewer;
/**
* @author <a href="mailto:joe@binamics.com">Joe Hudson</a>
*/
public class BuiltInFragment extends AbstractFragment {
private static final Map STRING_BUILT_INS = new HashMap();
private static final Map NUMBER_BUILT_INS = new HashMap();
private static final Map DATE_BUILT_INS = new HashMap();
private static final Map LIST_BUILT_INS = new HashMap();
private static final Map MAP_BUILT_INS = new HashMap();
private static final Map OBJECT_BUILT_INS = new HashMap();
static {
addToMap (OBJECT_BUILT_INS,
new Object[]{
"is_collection", Boolean.class, null, //$NON-NLS-1$
"is_macro", Boolean.class, null, //$NON-NLS-1$
"is_transform", Boolean.class, null, //$NON-NLS-1$
"string", String.class, null, //$NON-NLS-1$
"namespace", String.class, null, //$NON-NLS-1$
"default", String.class, new String[]{"value "}, //$NON-NLS-1$ //$NON-NLS-2$
"is_number", Boolean.class, null, //$NON-NLS-1$
"is_directive", String.class, null, //$NON-NLS-1$
"is_boolean", Boolean.class, null, //$NON-NLS-1$
"is_hash_ex", Boolean.class, null, //$NON-NLS-1$
"is_enumerable", Boolean.class, null, //$NON-NLS-1$
"is_date", Boolean.class, null, //$NON-NLS-1$
"is_node", Boolean.class, null, //$NON-NLS-1$
"exists", Boolean.class, null, //$NON-NLS-1$
"is_indexable", Boolean.class, null, //$NON-NLS-1$
"is_string", Boolean.class, null, //$NON-NLS-1$
"is_hash", Boolean.class, null, //$NON-NLS-1$
"is_sequence", Boolean.class, null, //$NON-NLS-1$
"if_exists", Boolean.class, null, //$NON-NLS-1$
"has_content", Boolean.class, null, //$NON-NLS-1$
"is_method", Boolean.class, null, //$NON-NLS-1$
"round", String.class, null, //$NON-NLS-1$
"floor", String.class, null, //$NON-NLS-1$
"ceiling", String.class, null, //$NON-NLS-1$
});
addToMap (STRING_BUILT_INS,
new Object[]{
"interpret", String.class, null, //$NON-NLS-1$
"matches", Boolean.class, new String[]{"expression"}, //$NON-NLS-1$ //$NON-NLS-2$
"html", String.class, null, //$NON-NLS-1$
"index_of", Number.class, new String[]{"substr"}, //$NON-NLS-1$ //$NON-NLS-2$
"right_pad", String.class, new String[]{"padAmount"}, //$NON-NLS-1$ //$NON-NLS-2$
"xml", String.class, null, //$NON-NLS-1$
"web_safe", String.class, null, //$NON-NLS-1$
"eval", null, null, //$NON-NLS-1$
"size", Number.class, null, //$NON-NLS-1$
"cap_first", String.class, null, //$NON-NLS-1$
"j_string", String.class, null, //$NON-NLS-1$
"first", String.class, null, //$NON-NLS-1$
"split", Collection.class, null, //$NON-NLS-1$
"upper_case", String.class, null, //$NON-NLS-1$
"last_index_of", String.class, null, //$NON-NLS-1$
"long", Number.class, null, //$NON-NLS-1$
"last", String.class, null, //$NON-NLS-1$
"starts_with", Boolean.class, null, //$NON-NLS-1$
"capitalize", String.class, null, //$NON-NLS-1$
"short", String.class, null, //$NON-NLS-1$
"ends_with", String.class, null, //$NON-NLS-1$
"chunk", Collection.class, null, //$NON-NLS-1$
"byte", String.class, null, //$NON-NLS-1$
"trim", String.class, null, //$NON-NLS-1$
"c", String.class, null, //$NON-NLS-1$
"chop_linebreak", String.class, null, //$NON-NLS-1$
"double", Number.class, null, //$NON-NLS-1$
"url", String.class, null, //$NON-NLS-1$
"replace", String.class, null, //$NON-NLS-1$
"uncap_first", String.class, null, //$NON-NLS-1$
"contains", Boolean.class, null, //$NON-NLS-1$
"left_pad", String.class, new String[]{"param"}, //$NON-NLS-1$ //$NON-NLS-2$
"length", Number.class, null, //$NON-NLS-1$
"rtf", String.class, null, //$NON-NLS-1$
"lower_case", String.class, null, //$NON-NLS-1$
"js_string", String.class, null, //$NON-NLS-1$
"word_list", String.class, null, //$NON-NLS-1$
});
addToMap (NUMBER_BUILT_INS,
new Object[]{
"string.currency", Boolean.class, new String[]{"format"}, //$NON-NLS-1$ //$NON-NLS-2$
"string", String.class, null, //$NON-NLS-1$
"number", Number.class, null, //$NON-NLS-1$
"new", String.class, null, //$NON-NLS-1$
"long", Number.class, null, //$NON-NLS-1$
"short", String.class, null, //$NON-NLS-1$
"double", Number.class, null, //$NON-NLS-1$
"int", Number.class, null, //$NON-NLS-1$
});
addToMap (DATE_BUILT_INS,
new Object[]{
"date", Date.class, null, //$NON-NLS-1$
"time", Date.class, null, //$NON-NLS-1$
"datetime", Date.class, null, //$NON-NLS-1$
"string", String.class, new String[]{"format"}, //$NON-NLS-1$ //$NON-NLS-2$
"string.short", String.class, null, //$NON-NLS-1$
"string.medium", String.class, null, //$NON-NLS-1$
"string.long", String.class, null, //$NON-NLS-1$
});
addToMap (LIST_BUILT_INS,
new Object[]{
"seq_contains", Boolean.class, new String[]{"value"}, //$NON-NLS-1$ //$NON-NLS-2$
"reverse", Collection.class, null, //$NON-NLS-1$
"size", Number.class, null, //$NON-NLS-1$
"last", Object.class, null, //$NON-NLS-1$
});
addToMap (MAP_BUILT_INS,
new Object[]{
"keys", Collection.class, null, //$NON-NLS-1$
});
}
private static void addToMap (Map map, Object[] arr) {
int i=0;
while (i<arr.length) {
map.put(
(String) arr[i++],
new ParameterSet (
(Class) arr[i++],
(String[]) arr[i++]));
}
}
public BuiltInFragment(int offset, String content) {
super(offset, content);
}
private String subContent = null;
public Class getReturnClass (Class parentClass, List fragments, Map context, IResource resource, IProject project) {
if (null == subContent) {
subContent = getContent();
int index = subContent.indexOf("("); //$NON-NLS-1$
if (index > 0) subContent = subContent.substring(0, index);
}
ParameterSet parameterSet = (ParameterSet) STRING_BUILT_INS.get(subContent);
if (null == parameterSet) parameterSet = (ParameterSet) NUMBER_BUILT_INS.get(subContent);
if (null == parameterSet) parameterSet = (ParameterSet) DATE_BUILT_INS.get(subContent);
if (null == parameterSet) parameterSet = (ParameterSet) LIST_BUILT_INS.get(subContent);
if (null == parameterSet) parameterSet = (ParameterSet) MAP_BUILT_INS.get(subContent);
if (null == parameterSet) parameterSet = (ParameterSet) OBJECT_BUILT_INS.get(subContent);
if (null != parameterSet) {
return parameterSet.getReturnClass();
}
else return null;
}
public ICompletionProposal[] getCompletionProposals (int subOffset, int offset, Class parentClass,
List fragments, ISourceViewer sourceViewer, Map context, IResource file, IProject project) {
if (instanceOf(parentClass, String.class)) {
return getCompletionProposals(subOffset, offset, STRING_BUILT_INS);
}
else if (instanceOf(parentClass, Number.class)) {
return getCompletionProposals(subOffset, offset, NUMBER_BUILT_INS);
}
else if (instanceOf(parentClass, Date.class)) {
return getCompletionProposals(subOffset, offset, DATE_BUILT_INS);
}
else if (instanceOf(parentClass, Collection.class) || instanceOf(parentClass, List.class)) {
return getCompletionProposals(subOffset, offset, LIST_BUILT_INS);
}
else if (instanceOf(parentClass, Map.class)) {
return getCompletionProposals(subOffset, offset, MAP_BUILT_INS);
}
else return getCompletionProposals(subOffset, offset, OBJECT_BUILT_INS);
}
private ICompletionProposal[] getCompletionProposals(int subOffset, int offset, Map values) {
if (offset == 0) return null;
String prefix = getContent().substring(0, subOffset-1);
List proposals = new ArrayList();
for (Iterator i=values.entrySet().iterator(); i.hasNext(); ) {
Map.Entry entry = (Map.Entry) i.next();
String key = (String) entry.getKey();
ParameterSet params = (ParameterSet) entry.getValue();
if (key.startsWith(prefix)) {
proposals.add(getCompletionProposal(key, params, offset, subOffset));
}
}
if (!values.equals(OBJECT_BUILT_INS)) {
values = OBJECT_BUILT_INS;
for (Iterator i=values.entrySet().iterator(); i.hasNext(); ) {
Map.Entry entry = (Map.Entry) i.next();
String key = (String) entry.getKey();
ParameterSet params = (ParameterSet) entry.getValue();
if (key.startsWith(prefix)) {
proposals.add(getCompletionProposal(key, params, offset, subOffset));
}
}
}
return completionProposals(proposals);
}
private ICompletionProposal getCompletionProposal (String key, ParameterSet params, int offset, int subOffset) {
if (null == params.getParameters() || params.getParameters().length == 0) {
return getCompletionProposal(offset, subOffset-1,
key, getContent());
}
else {
String replacementString = key + "()"; //$NON-NLS-1$
return new CompletionProposal (
replacementString, offset-subOffset+1,
getContent().length(), replacementString.length()-1);
}
}
private String getReplacementString (String key, ParameterSet values) {
if (null == values.getParameters()) {
return key;
}
else {
StringBuffer sb = new StringBuffer();
sb.append(key);
sb.append("("); //$NON-NLS-1$
// for (int i=0; i<values.getParameters().length; i++) {
// if (i > 0) sb.append(", ");
// sb.append(values.getParameters()[i]);
// }
sb.append(")"); //$NON-NLS-1$
return sb.toString();
}
}
}