/* 
@VaadinApache2LicenseForJavaFiles@
 */

package com.vaadin.server.widgetsetutils.metadata;

import java.util.Collection;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.vaadin.client.ui.AbstractComponentConnector;
import com.vaadin.shared.annotations.DelegateToWidget;

public class WidgetInitVisitor extends TypeVisitor {

    @Override
    public void visitConnector(TreeLogger logger, JClassType type,
            ConnectorBundle bundle) throws UnableToCompleteException {
        if (ConnectorBundle.isConnectedComponentConnector(type)) {
            JClassType createWidgetClass = findInheritedMethod(type,
                    "createWidget").getEnclosingType();
            boolean needsCreateWidgetSupport = createWidgetClass
                    .getQualifiedSourceName()
                    .equals(AbstractComponentConnector.class.getCanonicalName());

            JMethod getWidget = findInheritedMethod(type, "getWidget");
            JClassType widgetType = getWidget.getReturnType().isClass();

            JMethod getState = findInheritedMethod(type, "getState");
            JClassType stateType = getState.getReturnType().isClass();

            Collection<Property> properties = bundle.getProperties(stateType);
            boolean hasDelegateToWidget = false;
            for (Property property : properties) {
                DelegateToWidget delegateToWidget = property
                        .getAnnotation(DelegateToWidget.class);
                if (delegateToWidget != null) {
                    bundle.setNeedsDelegateToWidget(property);
                    String methodName = DelegateToWidget.Helper
                            .getDelegateTarget(property.getName(),
                                    delegateToWidget.value());
                    JMethod delegatedSetter = findInheritedMethod(widgetType,
                            methodName, property.getPropertyType());
                    if (delegatedSetter == null) {
                        logger.log(
                                Type.ERROR,
                                widgetType.getName()
                                        + "."
                                        + methodName
                                        + "("
                                        + property.getPropertyType()
                                                .getSimpleSourceName()
                                        + ") required by @DelegateToWidget for "
                                        + stateType.getName() + "."
                                        + property.getName()
                                        + " can not be found.");
                        throw new UnableToCompleteException();
                    }
                    bundle.setNeedsInvoker(widgetType, delegatedSetter);
                    hasDelegateToWidget = true;
                }
            }

            if (hasDelegateToWidget || needsCreateWidgetSupport) {
                bundle.setNeedsReturnType(type, getWidget);
                bundle.setNeedsGwtConstructor(widgetType);
            }

        }
    }
}

@@ -750,24 +750,86 @@
 or(type)) %7B%0A
+            // The class in which createWidget is implemented%0A
             
@@ -937,24 +937,25 @@
 singType();%0A
+%0A
             
@@ -958,60 +958,141 @@
     
-boolean needsCreateWidgetSupport = createWidget
+JMethod getWidget = findInheritedMethod(type, %22getWidget%22);%0A            JClassType widgetType = getWidget.getReturnType().is
 Class
+();%0A
 %0A   
@@ -1096,32 +1096,116 @@
             
-        
+// Needs GWT constructor if createWidget is not overridden%0A            if (createWidgetClass
 .getQualifie
@@ -1209,32 +1209,40 @@
 fiedSourceName()
+.equals(
 %0A               
@@ -1246,24 +1246,16 @@
         
-.equals(
 Abstract
@@ -1298,18 +1298,19 @@
 lName())
-;%0A
+) %7B
 %0A       
@@ -1318,55 +1318,180 @@
     
-JMethod getWidget =
+    bundle.setNeedsGwtConstructor(widgetType);%0A%0A                // Also needs widget type to
  find
-In
+ t
 he
+ 
 ri
-tedMethod
+ght GWT constructor%0A                bundle.setNeedsReturnType
 (type, 
-%22
 getW
@@ -1487,33 +1487,32 @@
 (type, getWidget
-%22
 );%0A            J
@@ -1514,69 +1514,70 @@
     
-JClassType widgetType = getWidget.getReturnType().isClass();%0A
+%7D%0A%0A            // Check state properties for @DelegateToWidget
 %0A   
@@ -1798,57 +1798,8 @@
 e);%0A
-            boolean hasDelegateToWidget = false;%0A
     
@@ -2010,32 +2010,105 @@
 dget != null) %7B%0A
+                    // Generate meta data required for @DelegateToWidget%0A
                 
@@ -2153,16 +2153,72 @@
 operty);
+%0A%0A                    // Find the delegate target method
 %0A       
@@ -3453,16 +3453,17 @@
 etter);%0A
+%0A
         
@@ -3478,136 +3478,66 @@
     
-hasDelegateToWidget = true;%0A                %7D%0A            %7D%0A%0A            if (hasDelegateToWidget %7C%7C needsCreateWidgetSupport) %7B%0A
+// GWT code needs widget type to find the target method%0A  
     
@@ -3540,32 +3540,34 @@
                 
+  
 bundle.setNeedsR
@@ -3614,50 +3614,9 @@
     
-bundle.setNeedsGwtConstructor(widgetType);
+%7D
 %0A   

Clarify logic and add some comments (#9561)