001// Copyright 2005 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007//     http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.hivemind.service.impl;
016
017import java.lang.reflect.Method;
018import java.lang.reflect.Modifier;
019import java.util.ArrayList;
020import java.util.HashSet;
021import java.util.Iterator;
022import java.util.List;
023import java.util.Set;
024
025import org.apache.hivemind.service.ClassFabUtils;
026import org.apache.hivemind.service.ClassFactory;
027import org.apache.hivemind.service.InterfaceFab;
028import org.apache.hivemind.service.InterfaceSynthesizer;
029import org.apache.hivemind.service.MethodSignature;
030
031/**
032 * @author Howard M. Lewis Ship
033 */
034public class InterfaceSynthesizerImpl implements InterfaceSynthesizer
035{
036    private ClassFactory _classFactory;
037
038    private static class Operation
039    {
040        private Set _interfaces = new HashSet();
041
042        private Set _interfaceMethods = new HashSet();
043
044        private Set _allMethods = new HashSet();
045
046        private List _interfaceQueue = new ArrayList();
047
048        public Set getInterfaces()
049        {
050            return _interfaces;
051        }
052
053        public Set getNonInterfaceMethodSignatures()
054        {
055            Set result = new HashSet(_allMethods);
056
057            result.removeAll(_interfaceMethods);
058
059            return result;
060        }
061
062        public void processInterfaceQueue()
063        {
064            while (!_interfaceQueue.isEmpty())
065            {
066                Class interfaceClass = (Class) _interfaceQueue.remove(0);
067
068                processInterface(interfaceClass);
069            }
070        }
071
072        private void processInterface(Class interfaceClass)
073        {
074            Class[] interfaces = interfaceClass.getInterfaces();
075
076            for (int i = 0; i < interfaces.length; i++)
077                addInterfaceToQueue(interfaces[i]);
078
079            Method[] methods = interfaceClass.getDeclaredMethods();
080
081            for (int i = 0; i < methods.length; i++)
082            {
083                MethodSignature sig = new MethodSignature(methods[i]);
084
085                _interfaceMethods.add(sig);
086            }
087        }
088
089        private void addInterfaceToQueue(Class interfaceClass)
090        {
091            if (_interfaces.contains(interfaceClass))
092                return;
093
094            _interfaces.add(interfaceClass);
095            _interfaceQueue.add(interfaceClass);
096        }
097
098        public void processClass(Class beanClass)
099        {
100            Class[] interfaces = beanClass.getInterfaces();
101
102            for (int i = 0; i < interfaces.length; i++)
103                addInterfaceToQueue(interfaces[i]);
104
105            Method[] methods = beanClass.getDeclaredMethods();
106
107            for (int i = 0; i < methods.length; i++)
108            {
109                Method m = methods[i];
110                int modifiers = m.getModifiers();
111
112                if (Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers))
113                    continue;
114
115                MethodSignature sig = new MethodSignature(m);
116
117                _allMethods.add(sig);
118            }
119        }
120
121    }
122
123    public Class synthesizeInterface(Class beanClass)
124    {
125        Operation op = new Operation();
126
127        explodeClass(beanClass, op);
128
129        return createInterface(beanClass, op);
130    }
131
132    void explodeClass(Class beanClass, Operation op)
133    {
134        Class current = beanClass;
135
136        while (current != Object.class)
137        {
138            op.processClass(current);
139
140            current = current.getSuperclass();
141        }
142
143        op.processInterfaceQueue();
144    }
145
146    Class createInterface(Class beanClass, Operation op)
147    {
148        String name = ClassFabUtils.generateClassName(beanClass);
149
150        return createInterface(name, op);
151    }
152
153    private Class createInterface(String name, Operation op)
154    {
155        InterfaceFab fab = _classFactory.newInterface(name);
156
157        Iterator i = op.getInterfaces().iterator();
158        while (i.hasNext())
159        {
160            Class interfaceClass = (Class) i.next();
161
162            fab.addInterface(interfaceClass);
163        }
164
165        i = op.getNonInterfaceMethodSignatures().iterator();
166        while (i.hasNext())
167        {
168            MethodSignature sig = (MethodSignature) i.next();
169
170            fab.addMethod(sig);
171        }
172
173        return fab.createInterface();
174    }
175
176    public void setClassFactory(ClassFactory classFactory)
177    {
178        _classFactory = classFactory;
179    }
180}