/** * Copyright 2002-2017 Evgeny Gryaznov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.textmapper.templates.objects; import org.textmapper.templates.api.EvaluationException; import org.textmapper.templates.api.IEvaluationStrategy; import org.textmapper.templates.api.SourceElement; import java.util.*; import java.util.stream.Collectors; public class JavaIxFactory implements IxFactory { @Override public IxObject asObject(Object o) { if (o instanceof IxObject) { return (IxObject) o; } if (o instanceof IxWrapper) { o = ((IxWrapper)o).getObject(); } if (o instanceof Map) { return new JavaMapIxObject((Map) o); } if (o instanceof int[]) { return new JavaIntArrayIxObject((int[]) o); } if (o instanceof short[]) { return new JavaShortArrayIxObject((short[]) o); } if (o instanceof Object[]) { return new JavaArrayIxObject((Object[]) o); } if (o instanceof List) { return new JavaListIxObject((List) o); } if (o instanceof Collection) { return new JavaCollectionIxObject((Collection) o); } return new DefaultJavaIxObject(o); } @Override public IxOperand asOperand(Object o) { if (o instanceof IxOperand) { return (IxOperand) o; } if (o instanceof IxWrapper) { o = ((IxWrapper)o).getObject(); } if (o instanceof Number) { return new JavaNumberIxObject((Number) o); } if (o instanceof String) { return new JavaStringIxObject((String) o); } return new DefaultIxOperand(o); } @Override public IxAdaptable asAdaptable(Object o) { if (o instanceof IxAdaptable) { return (IxAdaptable) o; } if (o instanceof IxWrapper) { o = ((IxWrapper)o).getObject(); } if (o instanceof Number) { return new JavaNumberIxObject((Number) o); } if (o instanceof String) { return new JavaStringIxObject((String) o); } if (o instanceof int[]) { return new JavaIntArrayIxObject((int[]) o); } if (o instanceof short[]) { return new JavaShortArrayIxObject((short[]) o); } if (o instanceof Object[]) { return new JavaArrayIxObject((Object[]) o); } if (o instanceof List) { return new JavaListIxObject((List) o); } if (o instanceof Collection) { return new JavaCollectionIxObject((Collection) o); } return new DefaultJavaIxObject(o); } @Override public void setStrategy(IEvaluationStrategy strategy) { } public static class JavaCollectionIxObject extends DefaultIxObject implements IxWrapper { protected Collection<?> collection; public JavaCollectionIxObject(Collection<?> collection) { this.collection = collection; } @Override protected String getType() { return "Collection"; } @Override public Object callMethod(SourceElement caller, String methodName, Object... args) throws EvaluationException { if (args == null) { switch (methodName) { case "first": return collection.isEmpty() ? null : collection.iterator().next(); case "last": if (collection instanceof List<?>) return ((List<?>) collection).get(collection.size() - 1); Object last = null; for (Object r : collection) { last = r; } return last; case "toSet": if (collection instanceof Set<?>) { return collection; } return new LinkedHashSet<>(collection); case "size": return collection.size(); } } else if (args.length == 1) { switch (methodName) { case "contains": return collection.contains(args[0]); case "indexOf": if (collection instanceof List<?>) { return ((List<?>) collection).indexOf(args[0]); } int i = 0; for (Object o : collection) { if (o != null && o.equals(args[0])) { return i; } i++; } return -1; case "union": if (args[0] != null) { Collection<Object> result = collection instanceof Set<?> ? new LinkedHashSet<>(collection) : new ArrayList<>(collection); if (args[0] instanceof Object[]) { Collections.addAll(result, (Object[]) args[0]); } else if (args[0] instanceof Collection<?>) { result.addAll((Collection<?>) args[0]); } else { result.add(args[0]); } return result; } return collection; } } return super.callMethod(caller, methodName, args); } @Override public Object getProperty(SourceElement caller, String propertyName) throws EvaluationException { if (propertyName.equals("length")) { return collection.size(); } throw new EvaluationException("do not know property `" + propertyName + "`"); } @Override public boolean is(String qualifiedName) throws EvaluationException { if("Collection".equals(qualifiedName)) { return true; } return JavaIsInstanceUtil.isInstance(getObject(), qualifiedName); } @Override public Iterator asSequence() throws EvaluationException { return collection.iterator(); } @Override public boolean asBoolean() { return collection.size() > 0; } @Override public Object getObject() { return collection; } } public static class JavaListIxObject extends JavaCollectionIxObject { public JavaListIxObject(List collection) { super(collection); } @Override public Object getByIndex(SourceElement caller, Object index) throws EvaluationException { if (index instanceof Integer) { int i = (Integer) index; if (i < 0 || i >= collection.size()) { throw new EvaluationException(i + " is out of 0.." + (collection.size() - 1)); } return ((List) collection).get(i); } else { throw new EvaluationException("index object should be integer"); } } @Override public boolean is(String qualifiedName) throws EvaluationException { if("List".equals(qualifiedName)) { return true; } return super.is(qualifiedName); //To change body of overridden methods use File | Settings | File Templates. } @Override protected String getType() { return "List"; } } public static class JavaArrayIxObject extends JavaListIxObject { private Object[] array; public JavaArrayIxObject(Object[] array) { super(new JavaArrayAdapter(array)); this.array = array; } @Override protected String getType() { return "Object[]"; } @Override public Object getObject() { return array; } } private class JavaMapIxObject extends DefaultIxObject implements IxWrapper { private Map map; public JavaMapIxObject(Map map) { this.map = map; } @Override public Object callMethod(SourceElement caller, String methodName, Object... args) throws EvaluationException { return new DefaultJavaIxObject(map).callMethod(caller, methodName, args); } @Override public Object getByIndex(SourceElement caller, Object index) throws EvaluationException { return map.get(index); } @Override public Object getProperty(SourceElement caller, String propertyName) throws EvaluationException { return map.get(propertyName); } @Override public boolean asBoolean() { return map.size() > 0; } @Override public boolean is(String qualifiedName) throws EvaluationException { return "Map".equals(qualifiedName) || JavaIsInstanceUtil.isInstance(getObject(), qualifiedName); } @Override protected String getType() { return "Map"; } @Override public Object getObject() { return map; } } private class JavaIntArrayIxObject extends DefaultIxObject implements IxWrapper { private int[] array; public JavaIntArrayIxObject(int[] array) { this.array = array; } @Override public Object getProperty(SourceElement caller, String propertyName) throws EvaluationException { if(propertyName.equals("length")) { return array.length; } return super.getProperty(caller, propertyName); } @Override public boolean asBoolean() { return array.length > 0; } @Override public boolean is(String qualifiedName) throws EvaluationException { return "int[]".equals(qualifiedName); } @Override public Object getByIndex(SourceElement caller, Object index) throws EvaluationException { if (index instanceof Integer) { int i = (Integer) index; if (i < 0 || i >= array.length) { throw new EvaluationException(i + " is out of 0.." + (array.length - 1)); } return array[i]; } else { throw new EvaluationException("index object should be integer"); } } @Override public Object callMethod(SourceElement caller, String methodName, Object... args) throws EvaluationException { if (args == null) { switch (methodName) { case "first": return array.length == 0 ? null : array[0]; case "last": return array.length == 0 ? null : array[array.length - 1]; case "toSet": LinkedHashSet<Integer> set = new LinkedHashSet<>(); for (int i : array) { set.add(i); } return set; case "size": return array.length; } } else if (args.length == 1) { if (methodName.equals("contains")) { for(int i : array) { if(new Integer(i).equals(args[0])) { return true; } } return false; } else if (methodName.equals("indexOf")) { for(int i = 0; i < array.length; i++) { if(new Integer(array[i]).equals(args[0])) { return i; } } return -1; } } return super.callMethod(caller, methodName, args); } @Override protected String getType() { return "int[]"; } @Override public Object getObject() { return array; } @Override public Iterator asSequence() throws EvaluationException { return new Iterator() { private int pos = 0; @Override public boolean hasNext() { return pos < array.length; } @Override public Object next() { return array[pos++]; } }; } } private class JavaShortArrayIxObject extends DefaultIxObject implements IxWrapper { private short[] array; public JavaShortArrayIxObject(short[] array) { this.array = array; } @Override public Object getProperty(SourceElement caller, String propertyName) throws EvaluationException { if(propertyName.equals("length")) { return array.length; } return super.getProperty(caller, propertyName); } @Override public boolean asBoolean() { return array.length > 0; } @Override public boolean is(String qualifiedName) throws EvaluationException { return "short[]".equals(qualifiedName); } @Override public Object getByIndex(SourceElement caller, Object index) throws EvaluationException { if (index instanceof Integer) { int i = (Integer) index; if (i < 0 || i >= array.length) { throw new EvaluationException(i + " is out of 0.." + (array.length - 1)); } return array[i]; } else { throw new EvaluationException("index object should be integer"); } } @Override public Object callMethod(SourceElement caller, String methodName, Object... args) throws EvaluationException { if (args == null) { switch (methodName) { case "first": return array.length == 0 ? null : array[0]; case "last": return array.length == 0 ? null : array[array.length - 1]; case "toSet": LinkedHashSet<Integer> set = new LinkedHashSet<>(); for (int i : array) { set.add(i); } return set; case "size": return array.length; } } else if (args.length == 1) { if (methodName.equals("contains")) { for(short i : array) { if(new Short(i).equals(args[0])) { return true; } } return false; } else if (methodName.equals("indexOf")) { for(int i = 0; i < array.length; i++) { if(new Short(array[i]).equals(args[0])) { return i; } } return -1; } } return super.callMethod(caller, methodName, args); } @Override protected String getType() { return "short[]"; } @Override public Object getObject() { return array; } } }