/* * Copyright (c) 2012 Diamond Light Source Ltd. * * 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 */ package uk.ac.diamond.scisoft.analysis.rpc.flattening; import uk.ac.diamond.scisoft.analysis.rpc.AbstractAnalysisRpcGenericDispatcher; import uk.ac.diamond.scisoft.analysis.rpc.internal.TypeHelper; /** * A wrapper type for <code>null</code> (on Java) or <code>None</code> (on Python) * <p> * While null/None is supported directly there is one case where knowing the intended type of the null is important, * when dealing with overloaded methods. * <p> * In Java if a class has these two overloaded methods: * * <pre> * void func(String s); * * void func(Integer i); * </pre> * * and you called them the compiler would determine the correct version based on the compile time types. As RPC has to * rely on only run time types when determining which method to call, a TypedNone can be used to distinguish to achieve * the equivalent to having written in Java: * * <pre> * o.func((String) null); * o.func((Integer) null); * </pre> * <p> * TypedNone's are immutable. * * @see AbstractAnalysisRpcGenericDispatcher */ public class TypedNone { private Class<? extends Object> clazz; /** * Construct a new TypedNone with the intended data type the None represents. * * @param clazz * class type of type null may not be <code>null</code> or a primitive class type (e.g. cannot be * {@link Integer#TYPE}) */ public TypedNone(Class<? extends Object> clazz) { if (clazz == null) throw new NullPointerException(); if (TypeHelper.isPrimitive(clazz)) throw new IllegalArgumentException("Cannot cast from null to primitive type"); this.clazz = clazz; } /** * Construct a new TypedNone with the intended data type the None represents. * * @param className * the name of the class suitable for passing to {@link Class#forName(String)} * @throws ClassNotFoundException * if className is invalid */ public TypedNone(String className) throws ClassNotFoundException { Class<? extends Object> clazz = Class.forName(className); if (TypeHelper.isPrimitive(clazz)) throw new IllegalArgumentException("Cannot cast from null to primitive type"); this.clazz = clazz; } /** * Return the data type represented by the TypedNone * * @return data type */ public Class<? extends Object> getType() { return clazz; } @Override public boolean equals(Object obj) { if (obj != null && obj instanceof TypedNone) { TypedNone typed = (TypedNone) obj; return clazz.equals(typed.clazz); } return false; } @Override public int hashCode() { return 7 + clazz.hashCode(); } @Override public String toString() { return "(" + clazz.getCanonicalName() + ")null"; } }