/* * Copyright (c) 2014. by Robusta Code and individual contributors * as indicated by the @authors tag. See the copyright.txt in the * distribution for a full listing of individual contributors. * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 io.robusta.rra.utils; import java.util.ArrayList; import java.util.HashMap; import java.util.Set; /** * <p> * It's just an ArrayList of {@link Couple} objects, somewhat more simple to use * than regular lists of Object[2] and allowing generics : <br/> * [(3, "Three"),(4, "44"),( 5, "cinquo"), (6, "6")] is a CoupleList<Integer, * String> * </p> * <p> * Using Hash or Couples is very convenient in Ajax world. For exemple if you * want all the students of your school, you will need id (for further calls) * and ScreenName for display . * </p> * <p> * This class is designed to be more simple than fast, but anyway with correct * speed. * </p> * * @author Nicolas Zozol * @todo 2 : change some method names * @see Couple * Created by Nicolas Zozol for Robusta Code */ public class CoupleList<LEFT, RIGHT> extends ArrayList<Couple<LEFT, RIGHT>> { public CoupleList() { } public CoupleList( HashMap<LEFT, RIGHT> map ) { Set<LEFT> entries = map.keySet(); for ( LEFT entry : entries ) { this.addCouple( entry, map.get( entry ) ); } } @Override public Couple<LEFT, RIGHT> get( int index ) { return super.get( index ); } /** * Adds a couple to your list * * @param e1 * LEFT element * @param e2 * RIGHT element */ public void addCouple( LEFT e1, RIGHT e2 ) { this.add( new Couple<LEFT, RIGHT>( e1, e2 ) ); } /** * returns the LEFT element at the specified index * * @param index * @return the LEFT element at the specified index */ public LEFT getLeftElement( int index ) { Couple<LEFT, RIGHT> couple = this.get( index ); return couple.getLeft(); } /** * returns the RIGHT element at the specified index * * @param index * @return the RIGHT element at the specified index */ public RIGHT getRightElement( int index ) { Couple<LEFT, RIGHT> couple = this.get( index ); return couple.getRight(); } /** * Returns an ArrayList<LEFT> of LEFT elements * * @return an ArrayList<LEFT> of LEFT elements */ public ArrayList<LEFT> getAllLeftElements() { ArrayList<LEFT> result = new ArrayList<LEFT>(); for ( int i = 0; i < this.size(); i++ ) { result.add( this.getLeftElement( i ) ); } return result; } /** * Returns an ArrayList<RIGHT> of RIGHT elements * * @return an ArrayList<RIGHT> of RIGHT elements */ public ArrayList<RIGHT> getAllRightElements() { ArrayList<RIGHT> result = new ArrayList<RIGHT>(); for ( int i = 0; i < this.size(); i++ ) { result.add( this.getRightElement( i ) ); } return result; } /** * <p> * Returns all RIGHT elements equals to Object o when o is a LEFT element, * and viceversa o can be sometimes on the left, sometime on the right. * </p> * <p> * For exemple <code>findMyLovers(3)</code> in [(3,"Three"),("Not Three", * 3),(4,5),(9,10)] will return ["Three", "Not Three"] * </p> * * @param o * The object to test * @return a list of matching objects */ public ArrayList findMyLovers( Object o ) { ArrayList result = new ArrayList(); /* Looking at first side */ for ( int i = 0; i < this.size(); i++ ) { if ( getLeftElement( i ).equals( o ) ) { result.add( getRightElement( i ) ); } if ( getRightElement( i ).equals( o ) ) { result.add( getLeftElement( i ) ); } } return result; } /** * * <p> * Returns the first LEFT object matching the RIGHT object o * </p> * <p> * For exemple <code>findMyLovers(3)</code> in [(3,"Three"),("Not Three", * 3),(4,5),(9,10)] will return <strong>"Not Three"</strong> * </p> * * @return first love of o */ public LEFT findMyFirstLoveInLeft( RIGHT o ) { for ( int i = 0; i < this.size(); i++ ) { if ( getRightElement( i ).equals( o ) ) { return getLeftElement( i ); } } return null; } /** * <p> * Returns the first RIGHT object matching the LEFT object o * </p> * <p> * For exemple <code>findMyLovers(3)</code> in [(3,"Three"),("Not Three", * 3),(4,5),(9,10)] will return <strong>"Three"</strong> * </p> * * @return first love of o */ public RIGHT findMyFirstLoveInRight( LEFT o ) { for ( int i = 0; i < this.size(); i++ ) { if ( getLeftElement( i ).equals( o ) ) { return getRightElement( i ); } } return null; } /** * <p> * Returns the first object matching the object o, whatever if it's on the * Right or the Left * </p> * * @return first love of o */ public Object findMyFirstLove( Object o ) { for ( int i = 0; i < this.size(); i++ ) { if ( getLeftElement( i ).equals( o ) ) { return getRightElement( i ); } if ( getRightElement( i ).equals( o ) ) { return getLeftElement( i ); } } return null; } /** * <p> * Sometimes a CoupleList is close of a HashMap. You can get it with this * function. Of course <strong>you may loose datas</strong> in your HashMap * if a Left element is not Unique. * </p> * <p> * LEFT will be the key, RIGHT the value ; use the getReversedList() * function if you wish to switch. * </p> * * @return a HashMap representation of the CoupleList, with possible loss of * datas. */ public HashMap<LEFT, RIGHT> getHashMap() { HashMap<LEFT, RIGHT> map = new HashMap<LEFT, RIGHT>(); for ( int i = 0; i < this.size(); i++ ) { map.put( this.getLeftElement( i ), this.getRightElement( i ) ); } return map; } /** * <p> * Using this function on [(3,"Three"),(4, "44"),( 5, "cinquo"), (6, "6")] * will return [("Three", 3),("44", 4),( "cinquo", 5), ("6", 6)] * </p> * <p> * You can't be confused if you use Generics. * </p> * * @return a new list, but with inverted Couples. */ public CoupleList<RIGHT, LEFT> reverse() { CoupleList<RIGHT, LEFT> result = new CoupleList<RIGHT, LEFT>(); for ( int i = 0; i < this.size(); i++ ) { result.addCouple( this.getRightElement( i ), this.getLeftElement( i ) ); } return result; } /** * <p> * Returns the Couples where the Object o is on the LEFT <strong>OR</strong> * the RIGHT. * </p> * <p> * It returns an empty list if nothing is found. It does NOT return null. * </p> * * @param o * Object to be found * @return couples containing o in LEFT <strong>or</strong> RIGHT */ public CoupleList<LEFT, RIGHT> findWhere( Object o ) { CoupleList<LEFT, RIGHT> list = new CoupleList(); for ( int i = 0; i < this.size(); i++ ) { if ( this.getLeftElement( i ).equals( o ) || this.getRightElement( i ).equals( o ) ) { list.add( this.get( i ) ); } } return list; } /** * <p> * Returns the Couples where the <strong>left</strong> is on the LEFT * <strong>AND right</strong> is on the RIGHT. * </p> * Returns an EMPTY coupleList when can't find the couple, and nerver a NULL * coupleList * * @param left * LEFT object wanted * @param right * RIGHT object wanted * @return couples containing left in LEFT <strong>and</strong> right in * RIGHT */ public CoupleList<LEFT, RIGHT> findWhere( LEFT left, RIGHT right ) { CoupleList<LEFT, RIGHT> list = new CoupleList(); for ( int i = 0; i < this.size(); i++ ) { if ( this.getLeftElement( i ).equals( left ) && this.getRightElement( i ).equals( right ) ) { list.add( this.get( i ) ); } } return list; } /** * <p> * This function removes all couples (left, right) from the list. * </p> * <p> * Only couples containg left <strong>AND</strong> right elements will be * removed. * </p> * * @param left * LEFT element to test * @param right * RIGHT element to test */ public void removeWhere( LEFT left, RIGHT right ) { CoupleList<LEFT, RIGHT> listToRemove = new CoupleList(); for ( int i = 0; i < this.size(); i++ ) { if ( this.getLeftElement( i ).equals( left ) && this.getRightElement( i ).equals( right ) ) { listToRemove.add( this.get( i ) ); } } /* Maintenant on enlève les éléments trouvés */ for ( int i = 0; i < listToRemove.size(); i++ ) { this.remove( listToRemove.get( i ) ); } } /** * removes all couples where o is in RIGHT or LEFT * * @param o */ public void removeWhere( Object o ) { ArrayList v = this.findWhere( o ); this.removeAll( v ); } /** * Easily builds a CoupleList : CoupleList.builder(3, "Three", 4, "44", 5, * "cinquo", 6, 6) will create the CoupleList :[(3, "Three"),(4, "44"),( 5, * "cinquo"), (6, 6)] * * @throws IllegalArgumentException * if number of params is not pair. */ public static <L, R> CoupleList build( Object... x ) { CoupleList<L, R> cpList = new CoupleList<L, R>(); int size = x.length; if ( size == 0 ) { return cpList; } if ( size % 2 != 0 ) { throw new IllegalArgumentException( "Var-args must be pair" ); } int index = 0; while ( index < size / 2 ) { cpList.addCouple( (L) x[2 * index], (R) x[2 * index + 1] ); index++; } return cpList; } /** * Returns a CoupleList where every objects are toString() values of initial * objects * * @return a stringified CoupleList */ public CoupleList<String, String> stringify() { CoupleList<String, String> result = new CoupleList<String, String>(); for ( Couple c : this ) { result.addCouple( c.getLeft().toString(), c.getRight().toString() ); } return result; } /** * Considers the CoupleList as a Name/Value list. Returns null if the name * is not found * * @param name * @param ignoreCase * @return */ public RIGHT getValue( String name, boolean ignoreCase ) { for ( Couple<LEFT, RIGHT> c : this ) { String val = c.getLeft().toString(); if ( ignoreCase ) { if ( val.equalsIgnoreCase( name ) ) { return c.getRight(); } } else { if ( val.equals( name ) ) { return c.getRight(); } } } return null; } }