001package com.identityworksllc.iiq.common; 002 003import java.util.*; 004 005/** 006 * A builder for MapTuple objects. These are objects that function as 007 * tuples, allowing access by either index or by key. To use this class, 008 * construct a new instance at the top of your operation, such as: 009 * 010 * MapTupleBuilder mtb = new MapTupleBuilder("identity", "accountName", "date"); 011 * 012 * Then, for each item, such as from a ResultSet, do this: 013 * 014 * MapTuple tuple = mtb.of(resultSet.getString("identity"), resultSet.getString("name"), resultSet.getDate("created")); 015 * 016 * In this example, the value for 'identity' can be accessed any of these ways: 017 * 018 * tuple.get("identity"); 019 * tuple.getAt(0); 020 * tuple.getFirst(); 021 * 022 */ 023public class MapTupleBuilder { 024 025 /** 026 * Gets the list of keys 027 */ 028 private final List<String> keys; 029 030 /** 031 * Constructs a new MapTupleBuilder, with the given list of keys. 032 * This constructor is private. One of the withKeys() methods should 033 * be used. 034 * 035 * Keys cannot be null and cannot be duplicated. 036 * 037 * @param keysList The list of keys 038 */ 039 private MapTupleBuilder(List<String> keysList) { 040 for(String k : Objects.requireNonNull(keysList)) { 041 Objects.requireNonNull(k, "Key in keys list cannot be null"); 042 } 043 044 Set<String> duplicatesRemoved = new HashSet<>(keysList); 045 if (duplicatesRemoved.size() != keysList.size()) { 046 throw new IllegalArgumentException("Duplicate keys are not allowed in MapTuple"); 047 } 048 049 this.keys = Collections.unmodifiableList(keysList); 050 } 051 052 /** 053 * Constructs a new MapTupleBuilder with the keys in the list. 054 * @param keys At least one key to use in the resulting tuples 055 * @return A builder with the given keys 056 */ 057 public static MapTupleBuilder withKeys(String... keys) { 058 if (keys.length == 0) { 059 throw new IllegalArgumentException("You must specify at least one key"); 060 } 061 List<String> keysList = new ArrayList<>(Arrays.asList(keys)); 062 return new MapTupleBuilder(keysList); 063 } 064 065 /** 066 * Constructs a new MapTupleBuilder with the keys in the list. 067 * @param keys A list containing at least one non-null key to use the resulting tuples 068 * @return A builder with the given keys 069 */ 070 public static MapTupleBuilder withKeys(List<String> keys) { 071 if (keys == null || keys.isEmpty()) { 072 throw new IllegalArgumentException("You must specify at least one key"); 073 } 074 return new MapTupleBuilder(keys); 075 } 076 077 /** 078 * Constructs a {@link MapTuple} pairing this builder's keys with the given 079 * values, both in order. The number of values must match the number of keys. 080 * 081 * @param values The values to add 082 * @return The resulting map 083 */ 084 public MapTuple of(Object... values) { 085 return ofList(Arrays.asList(values)); 086 } 087 088 /** 089 * Constructs a {@link MapTuple} pairing this builder's keys with the given 090 * values, both in order. The number of values must match the number of keys. 091 * 092 * @param values The values to add 093 * @return The resulting map 094 */ 095 public MapTuple ofList(List<Object> values) { 096 if (values.size() != keys.size()) { 097 throw new IllegalArgumentException("MapTuple argument mismatch: got " + values.size() + " values, expected " + keys.size()); 098 } 099 MapTuple result = new MapTuple(this.keys); 100 for(int i = 0; i < values.size(); i++) { 101 result.put(keys.get(i), values.get(i)); 102 } 103 return result; 104 } 105 106}