Remove redundant type arguments
[yangtools.git] / common / util / src / main / java / org / opendaylight / yangtools / util / ForwardingIdentityObject.java
1 /*
2  * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.util;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import com.google.common.collect.ForwardingObject;
14 import java.util.concurrent.ConcurrentHashMap;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.eclipse.jdt.annotation.NonNullByDefault;
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.opendaylight.yangtools.concepts.Delegator;
19
20 /**
21  * A {@link ForwardingObject} which additionally masks {@link #hashCode()}/{@link #equals(Object)} of a delegate object,
22  * so that it can be a data transfer object with data-dependent implementations of those contracts can be use in
23  * collections and maps which need to work on identity. This is useful in situations where identity equality needs to
24  * be used with the conjunction with the collections library, for example {@link ConcurrentHashMap}.  All instances are
25  * considered equal if they refer to the same delegate object.
26  *
27  * <p>
28  * Note this class forms its own equality domain, and its use may lead to surprising results, especially where
29  * {@link #toString()} is involved. For example a {@code Map.toString()} may end up emitting two keys which have the
30  * same String representation.
31  *
32  * @param <T> Type of wrapped object
33  * @author Robert Varga
34  */
35 @Beta
36 @NonNullByDefault
37 public abstract class ForwardingIdentityObject<T> extends ForwardingObject implements Delegator<T> {
38     protected ForwardingIdentityObject() {
39         // Mask public constructor
40     }
41
42     public static <T> ForwardingIdentityObject<T> of(final T obj) {
43         return checkedOf(requireNonNull(obj));
44     }
45
46     @Override
47     public final @NonNull T getDelegate() {
48         return delegate();
49     }
50
51     @Override
52     public final int hashCode() {
53         return System.identityHashCode(delegate());
54     }
55
56     @Override
57     public final boolean equals(final @Nullable Object obj) {
58         return obj == this || obj instanceof ForwardingIdentityObject
59                 && delegate() == ((ForwardingIdentityObject<?>) obj).delegate();
60     }
61
62     @Override
63     protected abstract @NonNull T delegate();
64
65     private static <T> ForwardingIdentityObject<T> checkedOf(final @NonNull T delegate) {
66         return new ForwardingIdentityObject<>() {
67             @Override
68             protected @NonNull T delegate() {
69                 return delegate;
70             }
71         };
72     }
73 }