/**
*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.*;
/**
* Create a awesome Set that is also having capability of indexers like a list
* Created by noga on 15/03/15.
*/
public class ListSet<T> extends HashSet<T> implements List<T> {
/**
* A list to shadow the hash map
*/
protected XList<T> behind;
public ListSet() {
this.behind = new XList<>();
}
public ListSet(Collection<? extends T> c) {
this();
this.addAll(c);
}
public ListSet(int initialCapacity) {
super(initialCapacity);
this.behind = new XList(initialCapacity);
}
public ListSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
this.behind = new XList(initialCapacity);
}
@Override
public boolean add(T t) {
if ( super.add(t)){
behind.add(t);
return true ;
}
return false ;
}
@Override
public void clear() {
behind.clear();
super.clear();
}
@Override
public boolean remove(Object o) {
if ( super.remove(o) ){
behind.remove(o);
return true;
}
return false;
}
@Override
public boolean removeAll(Collection<?> c) {
if( super.removeAll(c) ){
behind.clear();
behind.addAll(this);
return true;
}
return false;
}
@Override
public boolean addAll(Collection<? extends T> c) {
int size = size() ;
for(T t : c){
this.add(t);
}
return size != size();
}
@Override
public boolean addAll(int index, Collection<? extends T> c) {
int size = size() ;
int i = index ;
for(T t : c){
this.add(i++, t);
}
return size != size();
}
/***
* This is so that I can still index x['xxx'] and get a true false as if in contains
* @param o the object as index
* @return the item in the list
*/
public boolean get(Object o){
return super.contains(o);
}
@Override
public T get(int index) {
return behind.get(index);
}
@Override
public T set(int index, T element) {
if ( super.contains(element)){
behind.remove(element);
}else {
super.add(element);
}
behind.add(index,element);
return element;
}
@Override
public void add(int index, T element) {
set(index,element);
}
@Override
public T remove(int index) {
T t = behind.remove(index);
super.remove(t);
return t;
}
@Override
public int indexOf(Object o) {
if ( !super.contains(o)){
return -1;
}
return behind.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return indexOf(o);
}
@Override
public Iterator<T> iterator() {
return listIterator();
}
@Override
public ListIterator<T> listIterator() {
return behind.listIterator();
}
@Override
public ListIterator<T> listIterator(int index) {
return listIterator(index);
}
@Override
public List<T> subList(int fromIndex, int toIndex) {
return behind.subList(fromIndex,toIndex);
}
@Override
public String toString(){
StringBuffer buffer = new StringBuffer();
buffer.append("S{ ");
for(Object o : behind){
buffer.append(o).append(",");
}
String s = buffer.toString();
s = s.substring(0,s.length()-1);
s += " }";
return s;
}
@Override
public boolean equals(Object o){
if ( o == null ) return false ;
if ( o instanceof Set ){
return SetOperations.set_relation(this,(Set)o)
== SetOperations.SetRelation.EQUAL ;
}
if ( o instanceof List ){
return SetOperations.list_relation(this, o)
== SetOperations.SetRelation.EQUAL ;
}
return false ;
}
@Override
public int hashCode() {
return super.hashCode();
}
public ListSet map(Interpreter.AnonymousParam anon){
return behind.set(anon);
}
public ListSet set(Interpreter.AnonymousParam anon){
return map(anon);
}
public ListSet select(Interpreter.AnonymousParam anon){
if ( anon == null ) {
return new ListSet(this);
}
ListSet xList = new ListSet();
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 ( ret instanceof JexlException.Continue ){
if ( ((JexlException.Continue) ret).hasValue ){
ret = ((JexlException.Continue) ret).value ;
if (TypeUtility.castBoolean(ret,false)){
// ensure update to the variable is considered
item = anon.getVar( Script._ITEM_);
xList.add(item);
}
}
continue;
}
if (TypeUtility.castBoolean(ret,false)){
// ensure update to the variable is considered
item = anon.getVar( Script._ITEM_);
xList.add(item);
}
}
return xList;
}
}