001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2007-2010 ADEQUATE SYSTEMS SARL
004    
005      This file is part of Granite Data Services.
006    
007      Granite Data Services is free software; you can redistribute it and/or modify
008      it under the terms of the GNU Library General Public License as published by
009      the Free Software Foundation; either version 2 of the License, or (at your
010      option) any later version.
011    
012      Granite Data Services is distributed in the hope that it will be useful, but
013      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014      FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015      for more details.
016    
017      You should have received a copy of the GNU Library General Public License
018      along with this library; if not, see <http://www.gnu.org/licenses/>.
019      
020      
021      SLSB: This class and all the modifications to use it are marked with the 'SLSB' tag.
022     */
023    
024    package org.granite.generator.as3.reflect;
025    
026    import java.lang.annotation.Annotation;
027    import java.lang.reflect.Method;
028    import java.lang.reflect.Modifier;
029    import java.net.URL;
030    import java.util.ArrayList;
031    import java.util.Collections;
032    import java.util.HashSet;
033    import java.util.List;
034    import java.util.Set;
035    
036    import org.granite.generator.as3.reflect.JavaMethod.MethodType;
037    import org.granite.messaging.service.annotations.IgnoredMethod;
038    import org.granite.messaging.service.annotations.RemoteDestination;
039    
040    /**
041     * @author Franck WOLFF
042     */
043    public class JavaRemoteDestination extends JavaAbstractType {
044    
045            // /////////////////////////////////////////////////////////////////////////
046            // Fields.
047    
048            protected final Set<JavaImport> imports = new HashSet<JavaImport>();
049            protected final JavaType superclass;
050            protected final List<JavaMethod> methods;
051            protected final String destinationName;
052            protected final String channelId;
053            
054            // /////////////////////////////////////////////////////////////////////////
055            // Constructor.
056    
057            public JavaRemoteDestination(JavaTypeFactory provider, Class<?> type, URL url) {
058                    super(provider, type, url);
059    
060                    // Find superclass (controller filtered).
061                    this.superclass = provider.getJavaTypeSuperclass(type);
062    
063                    // Collect methods.
064                    this.methods = Collections.unmodifiableList(initMethods());
065    
066                    // Collect imports.
067                    if (superclass != null)
068                            addToImports(provider.getJavaImport(superclass.getType()));
069                    
070                    RemoteDestination rd = type.getAnnotation(RemoteDestination.class);
071                    if (rd != null) {
072                            destinationName = rd.id();
073                            channelId = rd.channel();
074                    }
075                    else {
076                            destinationName = null;
077                            channelId = null;
078                    }
079            }
080    
081            // /////////////////////////////////////////////////////////////////////////
082            // Properties.
083    
084            public Set<JavaImport> getImports() {
085                    return imports;
086            }
087    
088            protected void addToImports(JavaImport javaImport) {
089                    if (javaImport != null)
090                            imports.add(javaImport);
091            }
092    
093            public boolean hasSuperclass() {
094                    return superclass != null;
095            }
096    
097            public JavaType getSuperclass() {
098                    return superclass;
099            }
100    
101            public String getDestinationName() {
102                    return destinationName;
103            }
104    
105            public String getChannelId() {
106                    return channelId;
107            }
108            
109            public boolean isAnnotationPresent(Class<? extends Annotation> annotation) {
110                    return type.isAnnotationPresent(annotation);
111            }
112    
113            // /////////////////////////////////////////////////////////////////////////
114            // Utilities.
115    
116            protected List<JavaMethod> initMethods() {
117                    List<JavaMethod> methodMap = new ArrayList<JavaMethod>();
118    
119                    // Get all methods for interfaces: normally, even if it is possible in Java
120                    // to override a method into a inherited interface, there is no meaning
121                    // to do so (we just ignore potential compilation issues with generated AS3
122                    // classes for this case since it is always possible to remove the method
123                    // re-declaration in the child interface).
124                    Method[] methods = null;
125                    if (type.isInterface())
126                            methods = type.getMethods();
127                    else
128                            methods = type.getDeclaredMethods();
129                    
130                    for (Method method : methods) {
131                            if (Modifier.isPublic(method.getModifiers()) &&
132                                    !Modifier.isStatic(method.getModifiers()) &&
133                                    !method.isAnnotationPresent(IgnoredMethod.class)) {
134                                    for (Class<?> clazz : method.getParameterTypes()) {
135                                            if (clazz.isMemberClass() && !clazz.isEnum()) {
136                                                    throw new UnsupportedOperationException(
137                                                            "Inner classes are not supported (except enums): " + clazz
138                                                    );
139                                            }
140                                            addToImports(provider.getJavaImport(clazz));
141                                    }
142    
143                                    methodMap.add(new JavaMethod(method, MethodType.OTHER, this.provider));
144                            }
145                    }
146    
147                    return methodMap;
148            }
149            
150            public JavaInterface convertToJavaInterface() {
151                    return new JavaInterface(getProvider(), getType(), getUrl());
152            }
153    }