001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.openejb;
017:
018: import java.util.Arrays;
019: import java.util.regex.Matcher;
020: import java.util.regex.Pattern;
021: import java.io.Serializable;
022:
023: /**
024: * @version $Revision: 450758 $ $Date: 2006-09-28 01:40:18 -0700 $
025: */
026: public class MethodSpec implements Comparable, Serializable {
027: private static final long serialVersionUID = -1623511701541770312L;
028: private static final int AFTER_OTHER = 1;
029: private static final int BEFORE_OTHER = -1;
030: private final String methodIntf;
031: private final String methodName;
032: private final String[] parameterTypes;
033:
034: public MethodSpec(String methodIntf, String methodName,
035: String[] parameterTypes) {
036: this .methodIntf = methodIntf;
037: this .methodName = methodName;
038: this .parameterTypes = parameterTypes;
039: }
040:
041: public MethodSpec(String text) {
042: Pattern p = Pattern.compile("(\\S+) (\\S+)\\((\\S*)\\)");
043: Matcher m = p.matcher(text);
044: if (!m.matches()) {
045: throw new IllegalArgumentException(
046: "Text must match (\\S+) (\\S+)\\((\\S*)\\) : "
047: + text);
048: }
049: String intfString = m.group(1);
050: if (intfString.equals("all")) {
051: methodIntf = null;
052: } else {
053: methodIntf = intfString;
054: }
055: methodName = m.group(2);
056: String parameters = m.group(3);
057: if (parameters.length() > 0) {
058: parameterTypes = parameters.split(" *, *");
059: } else {
060: parameterTypes = null;
061: }
062: }
063:
064: public String getMethodIntf() {
065: return methodIntf;
066: }
067:
068: public String getMethodName() {
069: return methodName;
070: }
071:
072: public String[] getParameterTypes() {
073: return parameterTypes;
074: }
075:
076: public int hashCode() {
077: int result = 17;
078: result = 37 * result + methodIntf.hashCode();
079: result = 37 * result + methodName.hashCode();
080: for (int i = 0; i < parameterTypes.length; i++) {
081: result = 37 * result + parameterTypes[i].hashCode();
082: }
083: return result;
084: }
085:
086: public boolean equals(Object obj) {
087: if (obj == this ) {
088: return true;
089: }
090:
091: if (!(obj instanceof MethodSpec)) {
092: return false;
093: }
094:
095: MethodSpec methodSpec = (MethodSpec) obj;
096: return methodIntf.equals(methodSpec.methodIntf)
097: && methodName.equals(methodSpec.methodName)
098: && Arrays.equals(parameterTypes,
099: methodSpec.parameterTypes);
100: }
101:
102: public String toString() {
103: StringBuffer buffer = new StringBuffer();
104: if (methodIntf != null) {
105: buffer.append(methodIntf);
106: } else {
107: buffer.append("all");
108: }
109: buffer.append(" ").append(methodName).append('(');
110: if (parameterTypes != null) {
111: for (int i = 0; i < parameterTypes.length; i++) {
112: String parameterType = parameterTypes[i];
113: if (i > 0) {
114: buffer.append(',');
115: }
116: buffer.append(parameterType);
117: }
118: }
119: buffer.append(')');
120: return buffer.toString();
121: }
122:
123: public boolean matches(String methodIntf, String methodName,
124: String[] parameterTypes) {
125: assert methodIntf != null;
126: assert methodName != null;
127: assert parameterTypes != null;
128: if (this .methodIntf != null
129: && !methodIntf.equals(this .methodIntf)) {
130: //definitely wrong interface
131: return false;
132: }
133: //our interface is not specified or matches.
134: if (this .methodName.equals("*")) {
135: return true;
136: }
137: if (!methodName.equals(this .methodName)) {
138: //explicitly different method names
139: return false;
140: }
141: //same method names.
142: if (this .parameterTypes == null) {
143: return true;
144: }
145: return Arrays.equals(parameterTypes, this .parameterTypes);
146: }
147:
148: public int compareTo(Object o) {
149: if (!(o instanceof MethodSpec)) {
150: return -1;
151: }
152: if (this == o) {
153: return 0;
154: }
155: MethodSpec other = (MethodSpec) o;
156: if (parameterTypes != null) {
157: if (other.parameterTypes == null) {
158: //parameter types always come before no param types
159: return BEFORE_OTHER;
160: }
161: //both have param types
162: if (methodIntf != null) {
163: if (other.methodIntf == null) {
164: //method intf comes before no method intf.
165: return BEFORE_OTHER;
166: }
167: //both have method interfaces
168: int intfOrder = methodIntf.compareTo(other.methodIntf);
169: if (intfOrder != 0) {
170: return intfOrder;
171: }
172: //same interfaces
173: return compareMethod(other);
174: }
175: if (other.methodIntf != null) {
176: //they have method intf, we don't, they are first
177: return AFTER_OTHER;
178: }
179: //neither has methodIntf: sort by method name
180: return compareMethod(other);
181: }
182: //we don't have param types
183: if (other.parameterTypes != null) {
184: //they do, they are first
185: return AFTER_OTHER;
186: }
187: //neither has param types.
188: //explicit method name comes first
189: if (!methodName.equals("*")) {
190: if (other.methodName.equals("*")) {
191: return BEFORE_OTHER;
192: }
193: //both explicit method names.
194: //explicit method interface comes first
195: if (methodIntf != null) {
196: if (other.methodIntf == null) {
197: return BEFORE_OTHER;
198: }
199: //both explicit method intf. sort by intf, then methodName
200: int intfOrder = methodIntf.compareTo(other.methodIntf);
201: if (intfOrder != 0) {
202: return intfOrder;
203: }
204: //same interfaces
205: return methodName.compareTo(other.methodName);
206: }
207: if (other.methodIntf != null) {
208: //they have explicit method inft, we dont, they are first
209: return AFTER_OTHER;
210: }
211: //neither have explicit method intf.
212: return methodName.compareTo(other.methodName);
213: }
214: //we don't have explicit method name
215: if (!other.methodName.equals("*")) {
216: //they do, they are first
217: return AFTER_OTHER;
218: }
219: //neither has explicit method name
220: if (methodIntf != null) {
221: if (other.methodIntf == null) {
222: return BEFORE_OTHER;
223: }
224: return methodIntf.compareTo(other.methodIntf);
225: }
226: if (other.methodIntf != null) {
227: return AFTER_OTHER;
228: }
229: //neither has methodIntf or explicit methodName. problem.
230: throw new IllegalStateException("Cannot compare " + this
231: + " and " + other);
232: }
233:
234: private int compareMethod(MethodSpec other) {
235: int methodOrder = methodName.compareTo(other.methodName);
236: if (methodOrder != 0) {
237: return methodOrder;
238: }
239: //same method name, sort by params lexicographically
240: for (int i = 0; i < parameterTypes.length; i++) {
241: if (i == other.parameterTypes.length) {
242: //the other list is shorter, they are first
243: return AFTER_OTHER;
244: }
245: int paramOrder = parameterTypes[i]
246: .compareTo(other.parameterTypes[i]);
247: if (paramOrder != 0) {
248: return paramOrder;
249: }
250: }
251: //our list is shorter, we are first
252: return BEFORE_OTHER;
253: }
254: }
|