001: /*
002: * Copyright (C) 1999-2004 <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</a>
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package org.mandarax.kernel.meta;
020:
021: import org.mandarax.kernel.Function;
022: import org.mandarax.kernel.Session;
023: import org.mandarax.kernel.Term;
024:
025: /**
026: * Function that changes the type of a term.
027: * Supports casts to a superclass (or interface) and a subclass (or interface).
028: * If types (classes) are incompatible, the setters will throw an exception.
029: * To change types, they must first be reset to null.
030: * @author <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</A>
031: * @version 3.4 <7 March 05>
032: * @since 3.3
033: */
034:
035: public class CastFunction implements Function {
036: private Class targetType = null;
037: private Class[] sourceTypes = new Class[1];
038:
039: /**
040: * Return the return type.
041: * @see org.mandarax.kernel.Function#getReturnType()
042: */
043: public Class getReturnType() {
044: return targetType;
045: }
046:
047: /**
048: * Return the nsame of the function.
049: * @return a name
050: * @see org.mandarax.kernel.Constructor#getName()
051: */
052: public String getName() {
053: return new StringBuffer().append("cast [").append(
054: sourceTypes[0]).append(" -> ").append(targetType)
055: .append("]").toString();
056: }
057:
058: /**
059: * Return the structure of the function.
060: * @return an array of types (classes)
061: * @see org.mandarax.kernel.Constructor#getStructure()
062: */
063: public Class[] getStructure() {
064: return sourceTypes;
065: }
066:
067: /**
068: * Invoke the function.
069: * @param parameter the parameter
070: * @param session the session
071: * @see org.mandarax.kernel.Constructor#perform(org.mandarax.kernel.Term[], org.mandarax.kernel.Session)
072: */
073: public Object perform(Term[] parameter, Session session)
074: throws IllegalArgumentException,
075: UnsupportedOperationException {
076: return parameter[0].resolve(session); // "dynamic" casting does not make sense, the function only changes the declared type
077: }
078:
079: /**
080: * Indicates whether this function is executable.
081: * @return a boolean
082: */
083: public boolean isExecutable() {
084: return true;
085: }
086:
087: /**
088: * Get the source type.
089: * @return Returns the sourceType.
090: */
091: public Class getSourceType() {
092: return sourceTypes[0];
093: }
094:
095: /**
096: * Set the source type.
097: * @param sourceType The sourceType to set.
098: */
099: public void setSourceType(Class sourceType) {
100: check(sourceType, targetType);
101: this .sourceTypes[0] = sourceType;
102: }
103:
104: /**
105: * Returns the target type.
106: * @return Returns the targetType.
107: */
108: public Class getTargetType() {
109: return targetType;
110: }
111:
112: /**
113: * Set the target type.
114: * @param targetType The targetType to set.
115: */
116: public void setTargetType(Class targetType) {
117: check(sourceTypes[0], targetType);
118: this .targetType = targetType;
119: }
120:
121: /**
122: * Check the source and target type for compatibility.
123: * @param src the source type
124: * @param target the target type
125: * @throws an IllegalArgumentException if cast is not possible
126: */
127: private void check(Class src, Class target)
128: throws IllegalArgumentException {
129: if (src == null || target == null)
130: return;
131: if (src.isAssignableFrom(target)
132: || target.isAssignableFrom(src))
133: return;
134: else
135: throw new IllegalArgumentException(
136: "Cannot cast between types " + src + " and "
137: + target);
138: }
139:
140: }
|