/**
*Copyright 2016 Nabarun Mondal
* 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.noga.njexl.lang.extension.datastructures;
import com.noga.njexl.lang.Interpreter;
import com.noga.njexl.lang.JexlException;
import com.noga.njexl.lang.Script;
import com.noga.njexl.lang.extension.SetOperations;
import com.noga.njexl.lang.extension.TypeUtility;
import java.util.*;
/**
* An EXtended List -- XList.
* The purpose, doing some of the fantastic functional programming stuff
* Created by noga on 08/05/15.
*/
public class XList<T> extends ArrayList<T> {
public static class Pair implements Map.Entry{
public Object l;
public Object r;
public Pair(Object l, Object r){
this.l = l;
this.r = r;
}
public Object get(int index){
if ( index % 2 == 0 ) return l ;
return r ;
}
@Override
public String toString(){
return String.format("(%s,%s)",l,r);
}
@Override
public Object getKey() {
return l;
}
@Override
public Object getValue() {
return r;
}
@Override
public Object setValue(Object value) {
Object o = r;
r = value;
return o;
}
}
public XList() {
super();
}
public XList(Collection c) {
super(c);
}
public XList(T[] c) {
super();
for ( int i = 0 ; i < c.length; i++ ){
this.add(c[i]);
}
}
public XList(Map m){
super();
for ( Object k : m.keySet() ){
Object v = m.get(k);
Pair p = new Pair(k,v);
this.add((T) p);
}
}
public XList(int initialCapacity) {
super(initialCapacity);
}
@Override
public int indexOf(Object o){
if ( !( o instanceof Interpreter.AnonymousParam) ){
return super.indexOf(o);
}
Interpreter.AnonymousParam anon = (Interpreter.AnonymousParam)o;
Iterator iterator = iterator();
int i = -1;
while(iterator.hasNext()){
i++;
Object item = iterator.next();
anon.setIterationContext( this, item ,i);
Object ret = anon.execute();
if ( ret instanceof JexlException.Continue ){
if ( ((JexlException.Continue) ret).hasValue ){
boolean found = TypeUtility.castBoolean(((JexlException.Continue) ret).value, false);
if ( found ){ return i ; }
}
continue;
}
if (TypeUtility.castBoolean(ret,false)){
return i ;
}
}
return -1;
}
@Override
public int lastIndexOf(Object o){
if ( !( o instanceof Interpreter.AnonymousParam) ){
return super.lastIndexOf(o);
}
Interpreter.AnonymousParam anon = (Interpreter.AnonymousParam)o;
for ( int i = super.size() -1 ; i >= 0 ; i-- ){
Object item = get( i);
anon.setIterationContext( this, item ,i);
Object ret = anon.execute();
if ( ret instanceof JexlException.Continue ){
boolean found = TypeUtility.castBoolean(((JexlException.Continue) ret).value, false);
if ( found ){ return i ; }
continue;
}
if (TypeUtility.castBoolean(ret,false)){
return i;
}
}
return -1;
}
@Override
public boolean contains(Object o) {
int i = indexOf(o);
return ( i>= 0 );
}
public XList select(){
return select(null);
}
public XList select(Interpreter.AnonymousParam anon){
if ( anon == null ) {
return new XList(this);
}
XList xList = new XList();
Iterator iterator = iterator();
int i = -1;
while(iterator.hasNext()){
i++;
Object item = iterator.next();
anon.setIterationContextWithPartial( this, item ,i, xList);
Object ret = anon.execute();
if ( ret instanceof JexlException.Break ){
if ( ((JexlException.Break) ret).hasValue ){
ret = ((JexlException.Break) ret).value ;
if (TypeUtility.castBoolean(ret,false)){
// ensure update to the variable is considered
item = anon.getVar( Script._ITEM_);
xList.add(item);
}
}
break;
}
if (TypeUtility.castBoolean(ret,false)){
// ensure update to the variable is considered
item = anon.getVar( Script._ITEM_);
xList.add(item);
}
}
return xList;
}
public ListSet set(){
return set(null);
}
public ListSet set(Interpreter.AnonymousParam anon){
if ( anon == null ){
return new ListSet(this);
}
ListSet listSet = new ListSet();
int i = -1;
Iterator iterator = iterator();
while(iterator.hasNext()){
i++;
Object item = iterator.next();
anon.setIterationContextWithPartial( this, item ,i, listSet);
Object ret = anon.execute();
if ( ret instanceof JexlException.Continue ){
if ( ((JexlException.Continue) ret).hasValue ){
ret = ((JexlException.Continue) ret).value ;
listSet.add(ret);
}
continue;
}
if ( ret instanceof JexlException.Break ){
if ( ((JexlException.Break) ret).hasValue ){
ret = ((JexlException.Break) ret).value ;
listSet.add(ret);
}
break;
}
listSet.add(ret);
}
return listSet;
}
public XList map(Interpreter.AnonymousParam anon){
if ( anon == null ){
return new XList(this);
}
XList list = new XList();
int i = -1;
Iterator iterator = iterator();
while(iterator.hasNext()){
i++;
Object item = iterator.next();
anon.setIterationContextWithPartial( this, item ,i, list);
Object ret = anon.execute();
if ( ret instanceof JexlException.Continue ){
if ( ((JexlException.Continue) ret).hasValue ){
ret = ((JexlException.Continue) ret).value ;
list.add(ret);
}
continue;
}
if ( ret instanceof JexlException.Break ){
if ( ((JexlException.Break) ret).hasValue ){
ret = ((JexlException.Break) ret).value ;
list.add(ret);
}
break;
}
list.add(ret);
}
return list;
}
public HashMap<Object,List> mset(){
return mset(null);
}
public HashMap<Object,List> mset(Interpreter.AnonymousParam anon){
if ( anon == null ){
return SetOperations.multiset(this);
}
HashMap<Object,List> map = new HashMap<>();
Iterator iterator = iterator();
int i = -1;
while(iterator.hasNext()){
i++;
Object item = iterator.next();
anon.setIterationContextWithPartial(this, item, i, map);
Object key = anon.execute();
if ( key instanceof JexlException.Continue ){
if ( ((JexlException.Continue) key).hasValue ){
key = ((JexlException.Continue) key).value ;
if ( map.containsKey(key)){
map.get(key).add(item);
}else{
XList list = new XList();
list.add(item);
map.put(key,list);
}
}
continue;
}
if ( key instanceof JexlException.Break ){
if ( ((JexlException.Break) key).hasValue ){
key = ((JexlException.Break) key).value ;
if ( map.containsKey(key)){
map.get(key).add(item);
}else{
XList list = new XList();
list.add(item);
map.put(key,list);
}
}
break;
}
if ( map.containsKey(key)){
map.get(key).add(item);
}else{
XList list = new XList();
list.add(item);
map.put(key,list);
}
}
return map;
}
}