/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* 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:
* Google, Inc. - initial API and implementation
*******************************************************************************/
package com.windowtester.internal.runtime;
import java.io.Serializable;
import com.windowtester.internal.debug.Logger;
import com.windowtester.internal.runtime.bundle.BundleClassReference;
/**
* A class that stores the class information for a widget in the form of a
* string.
*/
public class ClassReference implements Serializable {
public static BundleClassReference forBundleClass(Class<?> cls) {
return BundleClassReference.forBundleClass(cls);
}
public static ClassReference forClass(Class<?> cls) {
return new ClassReference(cls);
}
/**
* @since 3.8.1
*/
public static ClassReference forName(String className) {
return new ClassReference(className);
}
/**
* A class that is used as a sentinel when class resolution in
* {@link ClassReference#getClassForName()} fails.
*
*/
public static final class UnresolvableClass{}
private static final long serialVersionUID = -5522094418456665521L;
/** name of the class **/
private final String name;
/** the class -- transient to avoid serialization**/
private transient Class<?> cls;
/**
* Constructor
* @param cls the class
*/
public ClassReference(Class<?> cls){
if (cls == null)
throw new IllegalArgumentException("class must not be null");
this.cls = cls;
this.name = cls.getName();
}
/**
* Constructor
* @param name the class name
*/
public ClassReference(String className){
if (className == null)
throw new IllegalArgumentException("class name must not be null");
name = className;
}
/**
* @return the class corresponding to the name
*/
public Class<?> getClassForName(){
if (!isResolved())
cls = resolveClass();
return cls;
}
private Class<?> resolveClass() {
try {
return Class.forName(getName());
} catch (ClassNotFoundException e) {
Logger.log(e);
/*
* I'd like to throw an exception here but there are lots
* of clients that call this code and don't expect an exception...
* As a an interim solution, we return a sentinel value that indicates
* that the class could not be resolved.
*/
return UnresolvableClass.class;
}
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (obj == null)
return false;
if (!(obj instanceof ClassReference))
return false;
ClassReference other = (ClassReference)obj;
//just test by string names
return other.name.equals(this.name);
}
/**
* @return the name of the class
*/
public String getName(){
return name;
}
/**
* Test whether this class reference refers to the given class.
* <p>
* Note: this test <b>will not</b> force the class to be resolved.
*/
public boolean refersTo(Class<?> cls) {
if (cls == null)
throw new IllegalArgumentException("class must not be null");
if (isResolved())
return getClassForName().equals(cls);
return cls.getName().equals(getName());
}
private boolean isResolved() {
return cls != null;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return "ClassReference(" + getName() + ")";
}
}