/*******************************************************************************
* Copyright (c) 2015 Google Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* C. Sean Young <csyoung@google.com> - Bug 436645
******************************************************************************/
package org.eclipse.ui.internal.navigator.extensions;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Arrays;
/**
* A reference meant to be a value object for an EvaluationReference key type;
* weakly holds an {@link EvaluationReference} (the reference itself, not the
* underlying object) representing this value's key. Used to support
* ReferenceQueue based cleanups in maps.
*
* Does not override equals or hashCode; uses identity comparison inherited from
* Object.
*
* @param <T>
* The type of object this reference points to.
*
* @see EvaluationReference
* @since 3.3
*/
public class EvaluationValueReference<T> extends SoftReference<T> {
private Reference<EvaluationReference<?>> refToKey;
/**
* @param referrent
* The object to be referenced
* @param key
* The key this value is associated with
*/
public EvaluationValueReference(T referrent, EvaluationReference<?> key) {
super(referrent);
this.refToKey = new WeakReference<EvaluationReference<?>>(key);
}
/**
* @param referrent
* The object to be referenced
* @param key
* The key this value is associated with
* @param queue
* The ReferenceQueue to register this instance in
*/
public EvaluationValueReference(T referrent, EvaluationReference<?> key,
ReferenceQueue<? super T> queue) {
super(referrent, queue);
this.refToKey = new WeakReference<EvaluationReference<?>>(key);
}
/**
* @return the key that this value was associated with, or null if this
* value has been cleared or the key has been collected.
*/
public EvaluationReference<?> getKey() {
return refToKey.get();
}
/**
* Facilitates "handing off" a particular instance of a key.
*
* @param otherValue
* the value ref to copy the key from.
*/
void swapKey(EvaluationValueReference<?> otherValue) {
Reference<EvaluationReference<?>> tmp = refToKey;
this.refToKey = otherValue.refToKey;
otherValue.refToKey = tmp;
}
/**
* Clears this reference and the underlying reference to the key.
*
* @see java.lang.ref.Reference#clear()
*/
@Override
public void clear() {
super.clear();
// This only clears our reference to the key, not the key itself.
refToKey.clear();
}
private static String toStringArrayAware(Object o) {
// Yea, this will miss primitive arrays, but nothing is using this for those yet.
if (o instanceof Object[]) {
return Arrays.toString((Object[]) o);
}
return String.valueOf(o);
}
@Override
public String toString() {
Object myRef = get();
return "EvaluationValueReference[" + (myRef == null ? "(collected)" : toStringArrayAware(myRef)) + ']'; //$NON-NLS-1$ //$NON-NLS-2$
}
}