View Javadoc
1   /*
2    * Copyright (c) 2001-2017, Zoltan Farkas All Rights Reserved.
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 2.1 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this program; if not, write to the Free Software
16   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17   *
18   * Additionally licensed with:
19   *
20   * Licensed under the Apache License, Version 2.0 (the "License");
21   * you may not use this file except in compliance with the License.
22   * You may obtain a copy of the License at
23   *
24   *      http://www.apache.org/licenses/LICENSE-2.0
25   *
26   * Unless required by applicable law or agreed to in writing, software
27   * distributed under the License is distributed on an "AS IS" BASIS,
28   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29   * See the License for the specific language governing permissions and
30   * limitations under the License.
31   */
32  package org.spf4j.base;
33  
34  import org.spf4j.io.Csv;
35  import com.google.common.base.Objects;
36  import java.beans.ConstructorProperties;
37  import java.io.IOException;
38  import java.io.StringReader;
39  import java.io.UncheckedIOException;
40  import java.util.LinkedHashMap;
41  import java.util.List;
42  import java.util.Map;
43  import javax.annotation.Nonnull;
44  import javax.annotation.Nullable;
45  
46  /**
47   *
48   * @author zoly
49   */
50  public class Pair<A, B> implements Map.Entry<A, B>, Writeable {
51  
52    //CHECKSTYLE:OFF
53    @Nullable
54    protected final A first;
55  
56    @Nullable
57    protected final B second;
58    //CHECKSTYLE:ON
59  
60    @ConstructorProperties({"first", "second"})
61    public Pair(@Nullable final A first, @Nullable final B second) {
62      this.first = first;
63      this.second = second;
64    }
65  
66    public static <A, B> Pair<A, B> of(@Nullable final A first, @Nullable final B second) {
67      return new Pair<>(first, second);
68    }
69  
70    /**
71     * Creates a pair from a str1,str2 pair.
72     *
73     * @param stringPair - pair in the format (a,b) csv pair.
74     * @return null if this is not a pair.
75     */
76    @Nullable
77    public static Pair<String, String> from(@Nonnull final String stringPair) {
78      if (stringPair.isEmpty()) {
79        return null;
80      }
81      int commaIdx = stringPair.indexOf(',');
82      if (commaIdx < 0) {
83        return null;
84      }
85      StringReader sr = new StringReader(stringPair);
86      StringBuilder first = new StringBuilder();
87      StringBuilder second = new StringBuilder();
88      int comma;
89      try {
90        comma = Csv.readCsvElement(sr, first);
91        if (comma != ',') {
92          return null;
93        }
94        int last = Csv.readCsvElement(sr, second);
95        if (last >= 0) {
96          return null;
97        }
98      } catch (IOException ex) {
99        throw new UncheckedIOException(ex);
100     }
101     return Pair.of(first.toString(), second.toString());
102   }
103 
104   public final A getFirst() {
105     return first;
106   }
107 
108   public final B getSecond() {
109     return second;
110   }
111 
112   @Override
113   public final boolean equals(final Object obj) {
114     if (obj == null) {
115       return false;
116     }
117     if (getClass() != obj.getClass()) {
118       return false;
119     }
120     final Pair<A, B> other = (Pair<A, B>) obj;
121     if (this.first != other.first && (this.first == null || !this.first.equals(other.first))) {
122       return false;
123     }
124     return (!(this.second != other.second && (this.second == null || !this.second.equals(other.second))));
125   }
126 
127   @Override
128   public final int hashCode() {
129     return Objects.hashCode(first, second);
130   }
131 
132   /**
133    * Overwrite to change string image.
134    * @return
135    */
136   @Override
137   public String toString() {
138     StringBuilder result = new StringBuilder(32);
139     writeTo(result);
140     return result.toString();
141   }
142 
143   @Override
144   public final void writeTo(final Appendable appendable) throws IOException {
145     Csv.writeCsvElement(first == null ? "" : first.toString(), appendable);
146     appendable.append(',');
147     Csv.writeCsvElement(second == null ? "" : second.toString(), appendable);
148   }
149 
150   public final List<Object> toList() {
151     return java.util.Arrays.asList(first, second);
152   }
153 
154   public static <K, V extends Object> Map<K, V> asMap(final Pair<K, ? extends V>... pairs) {
155     Map<K, V> result = new LinkedHashMap<>(pairs.length);
156     for (Pair<K, ? extends V> pair : pairs) {
157       result.put(pair.getFirst(), pair.getSecond());
158     }
159     return result;
160   }
161 
162   @Override
163   public final A getKey() {
164     return first;
165   }
166 
167   @Override
168   public final B getValue() {
169     return second;
170   }
171 
172   @Override
173   public final B setValue(final B value) {
174     throw new UnsupportedOperationException("Object not mutable");
175   }
176 
177 }