001: /*
002: * @(#)CxFactory.java
003: *
004: * Copyright (C) 2002-2003 Matt Albrecht
005: * groboclown@users.sourceforge.net
006: * http://groboutils.sourceforge.net
007: *
008: * Permission is hereby granted, free of charge, to any person obtaining a
009: * copy of this software and associated documentation files (the "Software"),
010: * to deal in the Software without restriction, including without limitation
011: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
012: * and/or sell copies of the Software, and to permit persons to whom the
013: * Software is furnished to do so, subject to the following conditions:
014: *
015: * The above copyright notice and this permission notice shall be included in
016: * all copies or substantial portions of the Software.
017: *
018: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
019: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
020: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
021: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
022: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
023: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
024: * DEALINGS IN THE SOFTWARE.
025: */
026:
027: package net.sourceforge.groboutils.junit.v1.iftc;
028:
029: /**
030: * Helper abstract class that aids in the setting of a unique and
031: * distinguishable name for a test case's factory.
032: * <P>
033: * As of 08-Dec-2002, the original constructor will NOT add the owning
034: * class's name to the factory <tt>toString()</tt> output. Since the
035: * Ant JUnit report is setup such that the concrete class's tests are
036: * organized under it, this is redundant information, and clutters the
037: * report.
038: *
039: * @author Matt Albrecht <a href="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
040: * @version $Date: 2003/05/24 16:42:13 $
041: * @since October 30, 2002
042: */
043: public abstract class CxFactory implements ICxFactory {
044: private String id;
045:
046: /**
047: * Specify a unique identifier for this specific factory within the
048: * context of the concrete test that is providing the factory. The
049: * <tt>CxFactory</tt> constructor will not add the test's class name to
050: * this string to create a distinguishable string to help debug the
051: * source of any errors caused by a factory's particular setup. If you
052: * want the owning class's name to appear in the id, use the alternate
053: * constructor.
054: *
055: * @param name the unique identifier within the context of the
056: * factory's owning test class. This cannot be <tt>null</tt>.
057: * @exception IllegalArgumentException thrown if <tt>name</tt>
058: * is <tt>null</tt>.
059: */
060: public CxFactory(String name) {
061: this (name, false);
062: }
063:
064: /**
065: * Specify a unique identifier for this specific factory within the
066: * context of the concrete test that is providing the factory. The
067: * <tt>CxFactory</tt> constructor may add the test's class name to
068: * this string to create a distinguishable string to help debug the
069: * source of any errors caused by a factory's particular setup,
070: * depending on the value of <tt>addClassName</tt>.
071: *
072: * @param name the unique identifier within the context of the
073: * factory's owning test class. This cannot be <tt>null</tt>.
074: * @param addClassName <tt>true</tt> if the owning class's name should
075: * be added to the id, and <tt>false</tt> if the name should be
076: * the ID itself.
077: * @exception IllegalArgumentException thrown if <tt>name</tt>
078: * is <tt>null</tt>.
079: * @since 07-Dec-2002
080: */
081: public CxFactory(String name, boolean addClassName) {
082: if (name == null) {
083: throw new IllegalArgumentException(
084: "factory name cannot be null.");
085: }
086:
087: // If this factory is within another class (i.e. an inner class
088: // or an anonymous class), then the owning class's name will be
089: // used instead, which is normally the test class's name.
090: if (addClassName) {
091: Class c = this .getClass();
092: String className = getOwningClassName(c);
093: this .id = className + "-" + name;
094: } else {
095: this .id = name;
096: }
097:
098: /* post condition - this can never happen.
099: Commented out for coverage numberes.
100: if (this.id == null)
101: {
102: throw new IllegalStateException(
103: "internal coding error: generated ID was null." );
104: }
105: */
106: }
107:
108: /**
109: * Override the Java-default toString, and provide our distinguishable
110: * name.
111: *
112: * @return the generated distinguishable name.
113: */
114: public String toString() {
115: /* Pre-condition - this should never happen.
116: Commented out for coverage numberes.
117: if (this.id == null)
118: {
119: throw new IllegalStateException(
120: "The internal id is null. "+
121: "An internal API coding mistake was made." );
122: }
123: */
124:
125: return this .id;
126: }
127:
128: /**
129: * Most factories have no need for a tearDown method, so a default
130: * (do-nothing) implementation has been provided here.
131: */
132: public void tearDown(Object implObject) throws Exception {
133: // do nothing
134: }
135:
136: // inherited from ImplFactory
137: public abstract Object createImplObject() throws Exception;
138:
139: /**
140: * Find the owning class name for the given class. For inner classes,
141: * this will return the parent class.
142: *
143: * @param c the class to find the owner
144: * @return the owning class' name.
145: */
146: private String getOwningClassName(Class c) {
147: if (c == null) {
148: throw new IllegalArgumentException("No null args.");
149: }
150:
151: Class lastOwner = c;
152: /*
153: This part does not work as expected: see the corresponding enemy
154: unit test for reasons.
155: Class owner = c.getDeclaringClass();
156: while (owner != null)
157: {
158: lastOwner = owner;
159: owner = owner.getDeclaringClass();
160: }
161: */
162: String className = lastOwner.getName();
163:
164: int pos = className.lastIndexOf('$');
165: if (pos > 0) {
166: className = className.substring(0, pos);
167: }
168: pos = className.lastIndexOf('.');
169: if (pos > 0) {
170: className = className.substring(pos + 1);
171: }
172: return className;
173: }
174: }
|