Source Code Cross Referenced for MethodOp.java in  » Science » Cougaar12_4 » org » cougaar » lib » contract » lang » op » reflect » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Science » Cougaar12_4 » org.cougaar.lib.contract.lang.op.reflect 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * <copyright>
003:         *  
004:         *  Copyright 1997-2004 BBNT Solutions, LLC
005:         *  under sponsorship of the Defense Advanced Research Projects
006:         *  Agency (DARPA).
007:         * 
008:         *  You can redistribute this software and/or modify it under the
009:         *  terms of the Cougaar Open Source License as published on the
010:         *  Cougaar Open Source Website (www.cougaar.org).
011:         * 
012:         *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013:         *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014:         *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015:         *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016:         *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017:         *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018:         *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019:         *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020:         *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021:         *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022:         *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023:         *  
024:         * </copyright>
025:         */
026:
027:        package org.cougaar.lib.contract.lang.op.reflect;
028:
029:        import java.util.*;
030:        import java.lang.reflect.*;
031:
032:        import org.cougaar.lib.contract.lang.*;
033:        import org.cougaar.lib.contract.lang.op.OpCodes;
034:
035:        /** 
036:         * "method" <code>Op</code>.
037:         * <p>
038:         * Behavior for overloaded methods may be incorrect(!).
039:         **/
040:
041:        public final class MethodOp extends OpImpl {
042:
043:            public Method meth;
044:            public Op[] argOps;
045:            public Object[] argBuf;
046:
047:            public static final Op[] zeroOps = {};
048:            private static final Object[] zeroArgs = {};
049:
050:            public MethodOp() {
051:            }
052:
053:            public final int getID() {
054:                return OpCodes.METHOD_ID;
055:            }
056:
057:            /**
058:             * <code>ReflectOp</code> should use <tt>parseMethod</tt>.
059:             */
060:            public final Op parse(final OpParser p) throws ParseException {
061:                throw new ParseException(
062:                        "Internal use should be \"parseMethod\"");
063:            }
064:
065:            /**
066:             * Parse the arguments for the given <code>Method</code>.
067:             */
068:            public final Op parseMethod(final Method meth, final OpParser p)
069:                    throws ParseException {
070:                TypeList origTypeList = p.cloneTypeList();
071:
072:                // gather some method info
073:                Class[] params = meth.getParameterTypes();
074:                int nparams = params.length;
075:                Class retClass = meth.getReturnType();
076:
077:                if (nparams == 0) {
078:                    // Assume that this is either (meth) or (apply meth u1),
079:                    // so we p.setTypeList to meth's retClass, expecting something like
080:                    //   (FooClass:getBar BarClass:test)
081:                    p.setTypeList(retClass);
082:                    Op u1 = p.nextOp();
083:                    p.setTypeList(retClass);
084:                    if (u1 == null) {
085:                        // (meth[]) is (meth)
086:                        this .meth = meth;
087:                        this .argOps = zeroOps;
088:                        this .argBuf = zeroArgs;
089:                        return this ;
090:                    } else {
091:                        Op u2 = p.nextOp();
092:                        if (u2 != null) {
093:                            // (meth[] arg1 .. argN) is broken!
094:                            throw new ParseException("Method \""
095:                                    + meth.getName() + "\" expecting "
096:                                    + "zero arguments but given additional "
097:                                    +
098:                                    //u1.getClass().getName());
099:                                    u1.getClass().getName() + "  !!added: "
100:                                    + u2.getClass().getName());
101:
102:                        }
103:                        // (meth[] u1) is (apply meth u1)
104:                        //
105:                        // This shorthand confuses both parser and user to no end...
106:                        //
107:                        int u1id = u1.getID();
108:                        if ((u1id == OpCodes.TRUE_ID)
109:                                || (u1id == OpCodes.FALSE_ID)) {
110:                            // (apply meth true) is (true)
111:                            // (apply meth false) is (false)
112:                            return u1;
113:                        } else {
114:                            // (apply meth u1)
115:                            // typical case
116:                            this .meth = meth;
117:                            this .argOps = zeroOps;
118:                            this .argBuf = zeroArgs;
119:                            ApplyOp aop = new ApplyOp(this , u1);
120:                            p.setTypeList(origTypeList);
121:                            return aop;
122:                        }
123:                    }
124:                } else {
125:                    // Expecting (meth[nArgs] arg1 .. argN), where the args are each
126:                    // given the meth's type.
127:                    this .meth = meth;
128:                    this .argOps = new Op[nparams];
129:                    this .argBuf = new Object[nparams];
130:                    int i = 0;
131:                    final int maxi = (nparams - 1);
132:                    while (true) {
133:                        Op ui = p.nextOp();
134:                        if (ui == null) {
135:                            // (meth[nArgs] arg1 .. argN-k) is broken!
136:                            throw new ParseException("Method \""
137:                                    + meth.getName() + "\" expecting "
138:                                    + nparams + " argument"
139:                                    + ((nparams > 1) ? "s" : "")
140:                                    + " but given only " + i);
141:                        }
142:                        // check type
143:                        Class reti = ui.getReturnClass();
144:                        if (!(params[i].isAssignableFrom(reti))) {
145:                            throw new ParseException("Method \""
146:                                    + meth.getName() + "\" argument " + i
147:                                    + " expected to be of type " + params[i]
148:                                    + " but given " + reti + " Op " + ui);
149:                        }
150:                        argOps[i] = ui;
151:                        // next param
152:                        i++;
153:                        // set arg type
154:                        if (i < maxi) {
155:                            // middle arg needs clone of type
156:                            p.setTypeList((TypeList) origTypeList.clone());
157:                        } else if (i == maxi) {
158:                            // last arg can take orig type
159:                            p.setTypeList(origTypeList);
160:                        } else {
161:                            // check for end of args
162:                            Op uN = p.nextOp();
163:                            if (uN != null) {
164:                                // (meth[nArgs] arg1 arg2 .. argN+k) is broken!
165:                                throw new ParseException("Method \""
166:                                        + meth.getName() + "\" expecting "
167:                                        + nparams + " argument"
168:                                        + ((nparams > 1) ? "s" : "")
169:                                        + " but given additional "
170:                                        + uN.getClass().getName());
171:                            }
172:                            break;
173:                        }
174:                    }
175:                    // (meth[nArgs] arg1 .. argN)
176:                    p.setTypeList(retClass);
177:                    return this ;
178:                }
179:            }
180:
181:            /**
182:             * Parse the arguments for the ambiguous <code>Method</code>, which
183:             * best matches an entry in the <code>List</code> of "possMeths".
184:             * <p>
185:             * More complex than <tt>parseMethod</tt>.
186:             */
187:            public final Op parseMethod(List possMeths, final OpParser p)
188:                    throws ParseException {
189:                TypeList origTypeList = p.cloneTypeList();
190:                int nPossMeths = possMeths.size();
191:
192:                // get the range of parameter lengths
193:                int minNParams = 0;
194:                int maxNParams = 0;
195:                for (int i = 0; i < nPossMeths; i++) {
196:                    Method mi = (Method) possMeths.get(i);
197:                    Class[] pi = mi.getParameterTypes();
198:                    int pin = pi.length;
199:                    if (i == 0) {
200:                        minNParams = pin;
201:                        maxNParams = pin;
202:                    } else if (pin < minNParams) {
203:                        minNParams = pin;
204:                    } else if (pin > maxNParams) {
205:                        maxNParams = pin;
206:                    }
207:                }
208:
209:                if (minNParams == 0) {
210:                    // maxNParams must be > 0, due to Java overloading rules
211:                    //
212:                    // potential confusion between "apply" method that takes zero 
213:                    // arguments and methods which take parameters.  Unable to 
214:                    // take the nextOp, since the TypeList is unknown.
215:                    //
216:                    // Consider:
217:                    //   "public String foo() {//1}"
218:                    //   "public Boolean foo(String s) {//2};"
219:                    //   "public String bar() {//3};"
220:                    //   "public Boolean bar(String s) {//4};"
221:                    //   (foo bar)
222:                    // is the "bar" used in an "apply":
223:                    //   apply "String foo()" as the value passed to "Boolean bar(String)"
224:                    //   bar(foo())
225:                    // or as a single "parameter":
226:                    //   use "String bar()" as the parameter in "Boolean foo(String)"
227:                    //   foo(bar())
228:                    //
229:                    // and it's worse when foo/bar are split between classes..
230:                    //
231:                    // solution: complain
232:                    //
233:                    StringBuffer sb = new StringBuffer();
234:                    sb.append("Method is ambiguous!\nPossible methods: {");
235:                    for (int i = 0; i < nPossMeths; i++) {
236:                        sb.append("\n    ");
237:                        sb.append(ReflectOp.toString((Method) possMeths.get(i),
238:                                true));
239:                    }
240:                    sb.append("\n}");
241:                    throw new ParseException(sb.toString());
242:                }
243:
244:                // Expecting (meth[nArgs] arg1 .. argN), where the args are each
245:                // given the meth's type and the number is unknown.
246:                List lOps = new ArrayList(maxNParams);
247:                while (true) {
248:                    Op ui = p.nextOp();
249:                    if (ui == null) {
250:                        break;
251:                    }
252:                    lOps.add(ui);
253:                    p.setTypeList((TypeList) origTypeList.clone());
254:                }
255:                int nlOps = lOps.size();
256:                this .argOps = new Op[nlOps];
257:                this .argBuf = new Object[nlOps];
258:                for (int i = 0; i < nlOps; i++) {
259:                    argOps[i] = (Op) lOps.get(i);
260:                }
261:
262:                // pick the method
263:                this .meth = pickClosestMethod(possMeths);
264:
265:                // (meth[nArgs] arg1 .. argN)
266:                p.setTypeList(meth.getReturnType());
267:                return this ;
268:            }
269:
270:            /**
271:             * Given a list of possible <code>Method</code>s and the <code>argOps</code>
272:             * already parsed, pick the "closest" matching <code>Method</code> in 
273:             * the list.
274:             * <p>
275:             * This is fairly tricky -- Java does something clever here...
276:             * <p>
277:             * <pre>
278:             * We'll do something OVERLY simple
279:             *   pick the one which matches exactly
280:             *   if none are exact, pick the single assignable method
281:             *   if multiple or none, complain
282:             * </pre>
283:             */
284:            private final Method pickClosestMethod(final List possMeths)
285:                    throws ParseException {
286:                int nargs = argOps.length;
287:                int nmeths = possMeths.size();
288:
289:                // assign ranks for each possible method
290:                //   -1 if any arg is not assignable
291:                //   +0 per exactly equal arg match
292:                //   +1 per assignable arg match not exactly equal
293:                int[] rank = new int[nmeths];
294:                int singleAssignableIdx = -1; // -1==unset, -2==multiple matches
295:                for (int i = 0; i < nmeths; i++) {
296:                    Method mi = (Method) possMeths.get(i);
297:                    Class[] pi = mi.getParameterTypes();
298:                    if (pi.length == nargs) {
299:                        int ri = 0;
300:                        for (int j = 0;; j++) {
301:                            if (j >= nargs) {
302:                                if (ri == 0) {
303:                                    // exact match.  it doesn't matter if this matched
304:                                    // an interface or implementation.
305:                                    return mi;
306:                                }
307:                                if (singleAssignableIdx == -1) {
308:                                    singleAssignableIdx = i; // unset --> set
309:                                } else {
310:                                    singleAssignableIdx = -2; // set/multi --> multi
311:                                }
312:                                break;
313:                            }
314:                            Class pij = pi[j];
315:                            Class arj = argOps[j].getReturnClass();
316:                            // compare parameter to given argument
317:                            if (pij.equals(arj)) {
318:                                // ri += 0;
319:                            } else if (pij.isAssignableFrom(arj)) {
320:                                ri += 1;
321:                            } else {
322:                                // not assignable
323:                                ri = -1;
324:                                break;
325:                            }
326:                        }
327:                        rank[i] = ri;
328:                    }
329:                }
330:                // pick the best method
331:                if (singleAssignableIdx >= 0) {
332:                    // give best single assignable match
333:                    return (Method) possMeths.get(singleAssignableIdx);
334:                } else if (singleAssignableIdx == -1) {
335:                    // none assignable
336:                    StringBuffer sb = new StringBuffer();
337:                    sb.append("Method matches none of these methods: {");
338:                    for (int i = 0; i < nmeths; i++) {
339:                        sb.append("\n    ");
340:                        sb.append(ReflectOp.toString((Method) possMeths.get(i),
341:                                true));
342:                    }
343:                    sb.append("\n}");
344:                    throw new ParseException(sb.toString());
345:                } else {
346:                    // multiple (ambiguous) possiblities!
347:                    StringBuffer sb = new StringBuffer();
348:                    sb.append("Method is ambiguous!" + "\nPossible methods: {");
349:                    for (int i = 0; i < nmeths; i++) {
350:                        if (rank[i] >= 0) {
351:                            // show possible method
352:                            sb.append("\n    ");
353:                            sb.append(ReflectOp.toString((Method) possMeths
354:                                    .get(i), true));
355:                        }
356:                    }
357:                    sb.append("\n}");
358:                    throw new ParseException(sb.toString());
359:                }
360:            }
361:
362:            public final boolean isReturnBoolean() {
363:                return (getReturnClass() == Boolean.TYPE);
364:            }
365:
366:            public final Class getReturnClass() {
367:                return meth.getReturnType();
368:            }
369:
370:            public final boolean execute(final Object o) {
371:                Object ret = operate(o);
372:                return ((Boolean) ret).booleanValue();
373:            }
374:
375:            public final Object operate(final Object o) {
376:                for (int i = 0; i < argBuf.length; i++) {
377:                    argBuf[i] = (argOps[i]).operate(o);
378:                }
379:                try {
380:                    return meth.invoke(o, argBuf);
381:                } catch (Exception e) {
382:                    throw new RuntimeException("Method \""
383:                            + getMethodString(true)
384:                            + "\" invocation resulted in Exception: " + e);
385:                }
386:            }
387:
388:            public final void setConst(final String key, final Object val) {
389:                for (int i = 0; i < argBuf.length; i++) {
390:                    argOps[i].setConst(key, val);
391:                }
392:            }
393:
394:            public final String getMethodString(boolean verbose) {
395:                return ReflectOp.toString(meth, verbose);
396:            }
397:
398:            public final void accept(TreeVisitor visitor) {
399:                // (method op0 op1 .. opN)
400:                visitor.visitWord(getMethodString(visitor.isVerbose()));
401:                if (argOps == zeroOps) {
402:                    // (method)
403:                } else if (argOps != null) {
404:                    // (method op0 op1 .. opN)
405:                    for (int i = 0; i < argOps.length; i++) {
406:                        argOps[i].accept(visitor);
407:                    }
408:                } else {
409:                    // (method ("?"))
410:                    visitor.visitConstant(null, "?");
411:                }
412:                visitor.visitEnd();
413:            }
414:        }
w__w__w_._j__a__v_a___2_s.__c_om___ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.