/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* 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 com.jfinal.template.stat.ast;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import com.jfinal.template.TemplateException;
import com.jfinal.template.stat.Location;
/**
* ForIteratorStatus
* 封装 #for( id : expr) 迭代语句状态,便于模板中获取
*
* 使用以下表达式可以模板中获取迭代状态:
* for.size 被迭代集合元素数量,不支持 Iterator 与 Iterable
* for.index 从 0 下始的下标
* for.count 从 1 开始的计数器
* for.first 是否第一个元素
* for.last 是否最后一个元素
* for.odd 是否第奇数个元素
* for.even 是否第偶数个元素
* for.outer 获取外层 for 对象,便于获取外层 for 循环状态
* 例如: for.outer.index
*/
public class ForIteratorStatus {
private Object outer;
private int index;
private int size;
private Iterator<?> iterator;
private Location location;
public ForIteratorStatus(Object outer, Object target, Location location) {
this.outer = outer;
this.index = 0;
this.location = location;
init(target);
}
@SuppressWarnings("unchecked")
private void init(Object target) {
if (target == null) {
size = 0;
iterator = NullIterator.me;
return ;
}
if (target instanceof Collection) {
size = ((Collection<?>)target).size();
iterator = ((Collection<?>)target).iterator();
return ;
}
if (target instanceof Map<?, ?>) {
size = ((Map<?, ?>)target).size();
iterator = new MapIterator(((Map<Object, Object>)target).entrySet().iterator());
return ;
}
if (target.getClass().isArray()) {
size = Array.getLength(target);
iterator = new ArrayIterator(target, size);
return ;
}
if (target instanceof Iterator) {
size = -1;
iterator = (Iterator<?>)target;
return ;
}
if (target instanceof Iterable) {
size = -1;
iterator = ((Iterable<?>)target).iterator();
return ;
}
if (target instanceof Enumeration) {
ArrayList<?> list = Collections.list((Enumeration<?>)target);
size = list.size();
iterator = list.iterator();
return ;
}
size = 1;
iterator = new SingleObjectIterator(target);
}
Iterator<?> getIterator() {
return iterator;
}
void nextState() {
index++;
}
public Object getOuter() {
return outer;
}
public int getIndex() {
return index;
}
public int getCount() {
return index + 1;
}
public int getSize() {
if (size >= 0) {
return size;
}
throw new TemplateException("No such method getSize() of the iterator", location);
}
public boolean getFirst() {
return index == 0;
}
public boolean getLast() {
return !iterator.hasNext();
}
public boolean getOdd() {
return index % 2 == 0;
}
public boolean getEven() {
return index % 2 != 0;
}
}
class MapIterator implements Iterator<Entry<Object, Object>> {
private Iterator<Entry<Object, Object>> iterator;
public MapIterator(Iterator<Entry<Object, Object>> iterator) {
this.iterator = iterator;
}
public boolean hasNext() {
return iterator.hasNext();
}
public Entry<Object, Object> next() {
return new ForEntry((Entry<Object, Object>)iterator.next());
}
public void remove() {
throw new UnsupportedOperationException();
}
}
class ArrayIterator implements Iterator<Object> {
private Object array;
private int size;
private int index;
ArrayIterator(Object array, int size) {
this.array = array;
this.size = size;
this.index = 0;
}
public boolean hasNext() {
return index < size;
}
public Object next() {
return Array.get(array, index++);
}
public void remove() {
throw new UnsupportedOperationException();
}
}
class SingleObjectIterator implements Iterator<Object> {
private Object target;
private boolean hasNext = true;
public SingleObjectIterator(Object target) {
this.target = target;
}
public boolean hasNext() {
return hasNext;
}
public Object next() {
if (hasNext) {
hasNext = false;
return target;
}
throw new NoSuchElementException();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
class NullIterator implements Iterator<Object> {
static final Iterator<?> me = new NullIterator();
private NullIterator() {
}
public boolean hasNext() {
return false;
}
public Object next() {
throw new NoSuchElementException();
}
public void remove() {
throw new UnsupportedOperationException();
}
}