Package com.habitsoft.kiyaa.rebind.typeinfo

Examples of com.habitsoft.kiyaa.rebind.typeinfo.ExpressionInfo


                        String setterName = "set" + capitalize(id);
                        memberDecls.add("public final void "+ setterName + "(String newValue) { panel.setText(\"" + id + "\", newValue); }");
                        myClass.addMethod(setterName, PrimitiveTypeInfo.VOID, RuntimeClassWrapper.STRING);
                       
                        //System.out.println("Using string build expression: "+stringBuildExpr+" for "+text);
                    ExpressionInfo expr = findAccessors(stringBuildExpr.toString(), true, true);
                    if(expr == null) {
                      logger.log(TreeLogger.ERROR, "Unable to resolve expression: "+stringBuildExpr, null);
                      throw new UnableToCompleteException();
                    }
                        //System.out.println("Got getter: "+expr.getter);
                    ExpressionInfo textExpr = new ExpressionInfo(expr.getOriginalExpr(), id, setterName, RuntimeClassWrapper.STRING);
                    if((expr.isConstant() || areConstant) && expr.hasSynchronousGetter()) {
                      sw.println(textExpr.copyStatement(expr));
                    } else if(areEarly) {
                        if(expr.hasSynchronousGetter())
                            earlyLoads.add(textExpr.copyStatement(expr));
                        else
                            earlyAsyncLoads.add(textExpr.asyncCopyStatement(expr, "group.<Void>member()", true));
                    } else {
                      asyncLoads.add(textExpr.asyncCopyStatement(expr, "group.<Void>member()", true));
                    }
                  }
              } finally {
                popLogger();
              }
View Full Code Here


      private void generateAttribute(GeneratorTypeInfo type, String name, final String key, final String value)
        throws UnableToCompleteException {
        LocalTreeLogger.pushLogger(logger.branch(TreeLogger.INFO, "Attribute "+key+"='"+value+"' in element "+name+" which is a "+type));
        try {
          ExpressionInfo baseExpr = new ExpressionInfo(name, name, type, false);
          ExpressionInfo attributeAccessors = findAccessors(baseExpr, key, true, false);
          // Automatically propagate some properties to the getViewWidget()
          if(attributeAccessors == null && key.matches("visible|width|height|title") && type.implementsInterface(commonTypes.view))
            attributeAccessors = findAccessors(baseExpr, "viewWidget."+key, true, false);
          if(key.equals("class")) {
            if(type.implementsInterface(commonTypes.view))
              attributeAccessors = findAccessors(baseExpr, "viewWidget.styleName", false, false);
            else if(type.isSubclassOf(commonTypes.uiObject))
              attributeAccessors = findAccessors(baseExpr, "styleName", false, false);
            else
              logger.log(TreeLogger.WARN, "Found attribute 'class' on something that isn't a View or Widget (a "+type+")");
          }
          boolean readOnly = false;
          boolean constant = false;
          boolean earlyLoad = false;
          boolean isExpr=false;
          String path = null;
          ExpressionInfo pathAccessors = null;
          if (((readOnly = (value.startsWith("${")
              || (earlyLoad = value.startsWith("@{"))
              || (constant = value.startsWith("%{"))))
              || value.startsWith("#{")) && value.endsWith("}")) {
              path = value.substring(2, value.length() - 1).trim();
              pathAccessors = findAccessors(path, false, true);
              isExpr=true;
          }
          String valueExpr;
          ActionInfo action;
          if ("class".equals(key) && pathAccessors == null) {
                      generateSetClass(type, name, value);
                  } else if ("style".equals(key)) {
                      generateSetStyle(type, name, key, value);
                  } else if ("binding".equals(key)) {
                      generateBinding(type, name, value);
                  } else if (attributeAccessors == null) {
                    if ("onclick".equals(key)) {
                        generateOnClickHandler(type, name, value, pathAccessors);
                    } else if ("onchange".equals(key)) {
                        generateOnChangeListener(type, name, value, pathAccessors);
                    } else if ("onfocus".equals(key)) {
                        generateOnFocusListener(type, name, value, pathAccessors);
                    } else if ("onblur".equals(key)) {
                        generateOnBlurListener(type, name, value, pathAccessors);
                    } else if ("onPressEnter".equalsIgnoreCase(key)) {
                        generateKeyPressHandler(type, name, value, "KEY_ENTER");
                    } else if ("onPressSpace".equalsIgnoreCase(key)) {
                        generateKeyPressHandler(type, name, value, "' '");
                    } else if ("onPressEscape".equalsIgnoreCase(key)) {
                        generateKeyPressHandler(type, name, value, "KEY_ESCAPE");
                    } else if ("onKeyPress".equalsIgnoreCase(key)) {
                        generateKeyPressHandler(type, name, value, null);
                    } else {
                        logger.log(TreeLogger.ERROR, "Unable to find a property '" + key + "' in " + type + "; value is '" + value + "'", null);
                        throw new UnableToCompleteException();
                    }
          } else if (!attributeAccessors.hasSetter()) {
              logger.log(TreeLogger.ERROR, "Unable to find a setter for attribute '" + key + "' in "
                              + type + "; value is '" + value + "', getter is "+attributeAccessors+" asyncGetter is "+attributeAccessors.getAsyncGetter(), null);
              throw new UnableToCompleteException();
          } else {
            final GeneratorTypeInfo attributeType = attributeAccessors.getType();
            if (attributeType.equals(commonTypes.action)
                      && (pathAccessors == null || !pathAccessors.hasGetter())
                      && (action = getAction(value, false)) != null) {
              if(attributeAccessors.hasSynchronousSetter() == false) {
                logger.log(TreeLogger.ERROR, "Async setters do not support for Actions yet.", null);
                throw new UnableToCompleteException();
              }
                sw.println(attributeAccessors.callSetter(action.toViewAction()).toString());
            } else if (path != null // If this is a ${...} or #{...}
                && commonTypes.value.equals(attributeType) // and the target attribute accepts a Value object
                  ) {
              valueExpr = getFieldValue(path);
              if(valueExpr == null) {
                logger.log(TreeLogger.ERROR, "Failed to evaluate expression to construct Value object for "+key+"="+path+" on "+type, null);
                throw new UnableToCompleteException();
              }
              if(attributeAccessors.hasSynchronousSetter() == false) {
                if(attributeAccessors.hasAsynchronousSetter())
                  logger.log(TreeLogger.ERROR, "Async setters not supported for Value yet; found use of async setter "+attributeAccessors.getAsyncSetter()+" for attribute "+key+" on "+type+" to store value "+path, null);
                else
                  logger.log(TreeLogger.ERROR, "No setter found for attribute "+key+" on "+type, null);
                throw new UnableToCompleteException();
              }
                sw.println(attributeAccessors.callSetter(valueExpr).toString());
            } else if (pathAccessors != null && pathAccessors.hasGetter()) {
                generateAttributeLoadSave(type, attributeAccessors, pathAccessors, readOnly, constant, earlyLoad);
            } else if (path != null && (valueExpr = getFieldValue(path)) != null) {
              logger.log(TreeLogger.WARN, "Using a Value "+valueExpr+"to read "+path+" for attribute "+key+"="+path);
              ExpressionInfo valueAccessors = findAccessors(new ExpressionInfo(path, valueExpr, commonTypes.value, true), "value", true, false);
              generateAttributeLoadSave(type, attributeAccessors, valueAccessors, readOnly, constant, earlyLoad);
            } else if(isExpr) {
              logger.log(TreeLogger.WARN, "Couldn't figure out how to set attribute "+key+" on "+type+"; couldn't find a getter for "+value, null);                     
            } else if (attributeType.equals(getType("java.lang.String"))) {
              ExpressionInfo valueAccessors = new ExpressionInfo(path, "\"" + backslashEscape(value) + "\"", getType("java.lang.String"), true);
              generateAttributeLoadSave(type, attributeAccessors, valueAccessors, true, true, true);
            } else if (attributeType.isEnum()) {
              if(attributeType.getEnumMembers().contains(value)) {
                    ExpressionInfo valueAccessors = new ExpressionInfo(path, attributeType.getParameterizedQualifiedSourceName()+"."+value, attributeType, true);
                    generateAttributeLoadSave(type, attributeAccessors, valueAccessors, true, true, true);
                } else {
                    logger.log(TreeLogger.ERROR, "Enum constant '" + value + "' not found in enum "+attributeType.getParameterizedQualifiedSourceName()+" for attribute "+key,
                        null);
                    throw new UnableToCompleteException();
                }
            } else if (attributeType.equals(getType("java.lang.Boolean"))) {
                if (!"true".equals(value) && !"false".equals(value)) {
                    logger.log(TreeLogger.ERROR, "Boolean attribute '" + key + "' should be true or false; got '"+value+"'",
                                    null);
                    throw new UnableToCompleteException();
                }
              ExpressionInfo valueAccessors = new ExpressionInfo(path, "Boolean." + value.toUpperCase(), attributeType, true);
              generateAttributeLoadSave(type, attributeAccessors, valueAccessors, true, true, true);
            } else if (attributeType.getName().equals("boolean")) {
                if (!"true".equals(value) && !"false".equals(value)) {
                    logger.log(TreeLogger.ERROR, "Boolean attribute '" + key + "' should be true or false; got '"+value+"'",
                                    null);
                    throw new UnableToCompleteException();
                }
              ExpressionInfo valueAccessors = new ExpressionInfo(path, value, attributeType, true);
              generateAttributeLoadSave(type, attributeAccessors, valueAccessors, true, true, true);
            } else if (attributeType.getName().equals("char")) {
              ExpressionInfo valueAccessors = new ExpressionInfo(path, "'"+backslashEscape(value)+"'", attributeType, true);
              generateAttributeLoadSave(type, attributeAccessors, valueAccessors, true, true, true);         
            } else if (attributeType.isPrimitive()) {
              ExpressionInfo valueAccessors = new ExpressionInfo(path, value, attributeType, true);
              generateAttributeLoadSave(type, attributeAccessors, valueAccessors, true, true, true);
            } else if (attributeType.equals(getType("java.lang.Class"))) {
                try {
                  ExpressionInfo valueAccessors = new ExpressionInfo(path, types.getType(value).getQualifiedSourceName()
                      + ".class", attributeType, true);
                  generateAttributeLoadSave(type, attributeAccessors, valueAccessors, true, true, true);
                } catch (NotFoundException caught) {
                    logger.log(TreeLogger.ERROR, "Unable to find class '" + value + "' for class attribute '"
                                    + key + "'", null);
View Full Code Here

      private void generateBinding(GeneratorTypeInfo type, String name, String value)
        throws UnableToCompleteException {
        if(value.startsWith("${") || value.startsWith("#{") || value.startsWith("%{") || value.startsWith("@{")) value = value.substring(2);
        if(value.endsWith("}")) value = value.substring(0, value.length()-1);
       
        ExpressionInfo accessors = findAccessors(value, false, false);
        if (accessors != null && accessors.hasSetter()) {
            sw.println(accessors.copyStatement(new ExpressionInfo(name, name, type, false)));
        } else {
            logger.log(TreeLogger.WARN, "Unable to find a "+(accessors == null?"property":"setter method")+" for binding expression: " + value, null);
        }
      }
View Full Code Here

            throw new UnableToCompleteException();
          }
        } else {
          boolean readOnly = false;
          String path = null;
          ExpressionInfo pathAccessors = null;
          if (((readOnly = (value.startsWith("${") || value.startsWith("@{") || value.startsWith("%{"))) || value.startsWith("#{")) && value.endsWith("}")) {
              path = value.substring(2, value.length() - 1).trim();
              pathAccessors = findAccessors(path, false, true);
              if(pathAccessors == null) {
                          logger.log(TreeLogger.ERROR, "Failed to evaluate parameter "+parameterName+" = "+value+" for method "+method, null);
                          throw new UnableToCompleteException();
              }
          }
          if(pathAccessors != null && !readOnly) {
            logger.log(TreeLogger.ERROR, "Using #{...} for a setter with multiple parameters is not supported, use ${...}; setter is "+method+" expression is "+value, null);
            throw new UnableToCompleteException();
          }
          String valueExpr;
          ActionInfo action;
          if (parameter.getType().isClass() != null
            && parameter.getType().isClass().isAssignableTo(commonTypes.action.getJClassType())
                && (pathAccessors == null || !pathAccessors.hasGetter())
                && (action = getAction(value, true)) != null) {
            paramString = action.toViewAction();
          } else if (path != null
                  && commonTypes.value.getJClassType().getErasedType().equals(parameter.getType().isClassOrInterface().getErasedType())
                    && (valueExpr = getFieldValue(path)) != null) {
            paramString = valueExpr;
          } else if (pathAccessors != null) {
            if(!pathAccessors.hasSynchronousGetter()) {
              logger.log(TreeLogger.ERROR, "Async/write-only values when calling a setter with multiple parameters is not supported currently.", null);
              throw new UnableToCompleteException();
            }
            paramString = pathAccessors.conversionExpr(JTypeWrapper.wrap(parameter.getType()));
            if(paramString == null) {
              logger.log(TreeLogger.ERROR, "Cannot convert "+pathAccessors.getType()+" '"+path+"' to "+parameter.getType()+" for call to "+method, null);
              throw new UnableToCompleteException();
            }
          // If we get here, there's no "${...}" or "#{...}" so it's a constant value / string or an action
          } else if(parameter.getType().getQualifiedSourceName().equals("java.lang.String")) {
              if(value.startsWith("${") || value.startsWith("%{") || value.startsWith("#{") || value.startsWith("@{"))
View Full Code Here

              try {
                  String existingValue = values.get(path);
                  if (existingValue != null) {
                      return existingValue;
                  }
                  ExpressionInfo accessors = findAccessors(path, true, true);
                  if (accessors != null) {
                    if(commonTypes.value.equals(accessors.getType())) {
                      if(!accessors.hasSynchronousGetter()) {
                        logger.log(TreeLogger.ERROR, "Can't handle an async Value getter yet; for "+path, null);
                        throw new UnableToCompleteException();
                        }
                      return accessors.getterExpr();
                    }
                      String valueName = "value" + values.size();
                      values.put(path, valueName);
            generateField(valueName, commonTypes.value);
                      sw.println(valueName + " = new Value() { ");
                      if(accessors.hasSynchronousGetter()) {
                          sw.indentln("public void getValue(AsyncCallback callback) { callback.onSuccess(" + accessors.getterExpr() + "); } ");
                      } else if(accessors.hasAsynchronousGetter()) {
                          sw.indentln("public void getValue(AsyncCallback callback) {\n\t\t\t\t"+accessors.callAsyncGetter("callback")+";\n\t\t\t\t} ");
                      } else {
                          sw.indentln("public void getValue(AsyncCallback callback) { callback.onFailure(null); } ");
                      }
                      if (accessors.hasSynchronousSetter()) {
                          sw.indentln("public void setValue(Object value, AsyncCallback callback) { try {\n\t\t\t\t" +
                              accessors.callSetter(ExpressionInfo.converter("value", RuntimeClassWrapper.OBJECT, accessors.getType())) +
                                  "\n\t\t\t\tcallback.onSuccess(null); } catch(Throwable caught) { callback.onFailure(caught); } }");
                      } else if(accessors.hasAsynchronousSetter()) {
                          sw.indentln("public void setValue(Object value, AsyncCallback callback) { " +
                              accessors.callAsyncSetter(ExpressionInfo.converter("value", RuntimeClassWrapper.OBJECT, accessors.getType()), "callback")
                              +"}");
                         
                      } else {
                          sw.indentln("public void setValue(Object value, AsyncCallback callback) { callback.onFailure(null); }");
                      }
View Full Code Here

           
      ActionInfo getAction(String expr, boolean innerClass) throws UnableToCompleteException {
                final Matcher matcher = Pattern.compile("^on\\s+([^:]+):\\s*(.*)$").matcher(expr);
                final String targetView;
                if(matcher.matches()) {
                    final ExpressionInfo targetViewExpr = findAccessors(matcher.group(1), innerClass, false);
                    if(targetViewExpr == null || !targetViewExpr.hasSynchronousGetter()) {
                        logger.log(TreeLogger.ERROR, "Unable to resolve target view expression '"+matcher.group(1)+"' for action '"+expr+"'", null);
                        throw new UnableToCompleteException();
                    }
                    targetView = targetViewExpr.getGetter();
                    expr = matcher.group(2);
                } else {
                    targetView = getRootView(innerClass);
                }
         
View Full Code Here

       * running.  This can be used to avoid full save/load cycles when save/load is slow or unnecessary.
       */
            protected ActionInfo getAction(String path, String targetView, boolean saveBefore, boolean loadAfter) throws UnableToCompleteException {
              if((path.startsWith("${") || path.startsWith("#{") || path.startsWith("%{") || path.startsWith("@{")) && path.endsWith("}")) {
                path = path.substring(2, path.length()-1);
                    ExpressionInfo expr = findAccessors(path, true, false);
                    if(expr != null && expr.hasSynchronousGetter())
                    return new ActionInfo(path, expr.getGetter(), true, true, targetView, saveBefore, loadAfter, 0);
                    logger.log(TreeLogger.ERROR, "Unable to resolve action variable at path "+path, null);
                    throw new UnableToCompleteException();
              }
              if(path.startsWith(";")) {
                saveBefore = false;
                path = path.substring(1).trim();
              }
              if(path.endsWith(";")) {
                loadAfter = false;
                path = path.substring(0, path.length()-1).trim();
              }
              String actionKey = path+","+saveBefore+","+targetView+","+loadAfter;
              ActionInfo existing = actions.get(actionKey);
                if (existing != null)
                    return existing;
                String[] actionSeries = path.split("\\s*;\\s*");
                if(actionSeries.length > 1) {
                  ArrayList<String> actionList = new ArrayList<String>();
                  int timeout=0;
                  for (int i = 0; i < actionSeries.length; i++) {
                    ActionInfo action = getAction(actionSeries[i], targetView, false, false);
                    timeout += action.getTimeout();
                    if(action != null && action.getAction() != null)
                        actionList.add(action.toActionCtor());
                  }
                  String ctor = "new ActionSeries("+StringUtils.join(actionList, ",\n\t\t\t")+")";
                    return new ActionInfo(path, ctor, true, true, targetView, saveBefore, loadAfter, timeout);
                }

                if("".equals(path) || "null".equals(path)) {
                  //sw.println("final Action " + actionName + " = new ViewAction(null, "+rootView+", "+saveBefore+", "+loadAfter+");");
                  return new ActionInfo(path, null, true, true, targetView, saveBefore, loadAfter, 0);
                }
               
                String[] args;
                String preargs = path;
                int argstart;
                if (path.endsWith(")") && (argstart = smartIndexOf(path, '(')) != -1) {
                    args = path.substring(argstart + 1, path.length() - 1).split("\\s*,\\s*");
                    // Check for an empty parameter list
                    if(args.length == 1 && args[0].length() == 0)
                        args = new String[0];
                    preargs = path.substring(0, argstart);
                } else {
                    args = new String[0];
                }

                int assignmentIndex = smartIndexOf(preargs, '=');
                if(assignmentIndex != -1) {
                  String left = path.substring(0, assignmentIndex).trim();
                  String right = path.substring(assignmentIndex+1).trim();
                  ExpressionInfo lvalue = findAccessors(left, true, true);
                  if(lvalue == null || (lvalue.hasSynchronousSetter() == false && lvalue.hasAsynchronousSetter() == false)) {
                    logger.log(TreeLogger.ERROR, "Can't find any setter for the left side of "+path, null);
                    throw new UnableToCompleteException();
                  }
                  ExpressionInfo rvalue = findAccessors(right, true, true);
                  if(rvalue == null || !rvalue.hasGetter()) {
                    logger.log(TreeLogger.ERROR, "Can't find any getter for the right side of "+path, null);
                    throw new UnableToCompleteException();
                  }
                  if(lvalue.hasAsynchronousSetter() == false && rvalue.hasAsynchronousGetter() == false) {
                        return new ActionInfo(path, lvalue.copyStatement(rvalue), false, false, targetView, saveBefore, loadAfter, 0);
                  } else {
                      return new ActionInfo(path, lvalue.asyncCopyStatement(rvalue, "callback", false), false, true, targetView, saveBefore, loadAfter, 0);
                  }
                } else {
                    int objectPathEnd = preargs.lastIndexOf('.');
                    String objectPath;
                    String methodName;
                    String getter;
                    final GeneratorTypeInfo objectType;
                    boolean searchingThis = (objectPathEnd == -1);
                    if (searchingThis) {
                        objectPath = getter = "this";
                        objectType = myClass;
                        methodName = preargs;
                    } else {
                        objectPath = preargs.substring(0, objectPathEnd);
                        methodName = preargs.substring(objectPathEnd+1);
                        ExpressionInfo accessors = findAccessors(objectPath, true, false);
                        if (accessors == null || !accessors.hasSynchronousGetter() || accessors.getType() == null) {
                            logger.log(TreeLogger.ERROR, "Can't find any object for " + objectPath + " for action "+ path, null);
                            return null;
                        }
                        getter = accessors.getterExpr();
                        objectType = accessors.getType();
                        if (objectType.isPrimitive()) {
                            logger.log(TreeLogger.ERROR, "Can't call a method on a primitive "
                                            + accessors.getType() + " for expression " + path, null);
                            throw new UnableToCompleteException();
                        }
                    }
   
                    boolean asyncMethod = false;
                    GeneratorMethodInfo actionMethod = null;
                    GeneratorTypeInfo searchType = objectType;
                    if(searchType == null) {
                        logger.log(TreeLogger.ERROR, "Can't call a method on a " + objectType + " for expression " + path, null);
                        throw new UnableToCompleteException();
                    }
                    final String asyncCallbackClassName = AsyncCallback.class.getName();
                    for(;;) {
                      // Look for a synchronous action method with the right number of parameters
                      actionMethod = searchType.findMethodMatching(methodName, true, PrimitiveTypeInfo.VOID, new GeneratorTypeInfo[args.length]);
                      if(actionMethod != null) {
                        asyncMethod = false;
                        break;
                      }
                     
                      // Look for the method with one extra parameter which is the async callback
                      GeneratorTypeInfo[] asyncParamTypes = new GeneratorTypeInfo[args.length+1];
                      asyncParamTypes[args.length] = commonTypes.asyncCallback;
            actionMethod = searchType.findMethodMatching(methodName, true, PrimitiveTypeInfo.VOID, asyncParamTypes );
                      if(actionMethod != null) {
                        asyncMethod = true;
                        break;
                      }
                        if(searchingThis && searchType instanceof GeneratedInnerClassInfo) {
                          searchType = searchType.getFieldType(PARENT_VIEW_FIELD_NAME, true);
                          if(searchType == null)
                            break;
                          getter = getter+"."+PARENT_VIEW_FIELD_NAME;
                          //System.out.println("Looking up into "+searchType+" getter "+getter+" for "+methodName);
                        } else break;
                    }
                    if (actionMethod == null) {
                        logger.log(TreeLogger.WARN, "getAction(): Unable to find a method with the right number of arguments ("
                                        + args.length + " [ + AsyncCallback]) with name '" + methodName + "' on " + objectType + " in " + myClass
                                        + " for expression " + path +" searchingThis = "+searchingThis, null);
                        return null;
                    }
   
                    for (int i = 0; i < args.length; i++) {
                        String arg = args[i].trim();
                        ExpressionInfo argAccessors = findAccessors(arg, true, false);
                        if (argAccessors == null) {
                            logger.log(TreeLogger.ERROR, "Couldn't evaluate '" + arg + "' as argument to '" + path + "'", null);
                            throw new UnableToCompleteException();
                        }
                        args[i] = argAccessors.conversionExpr(actionMethod.getParameterTypes()[i]);
                    }
   
                    String methodCall;
                    if (getter.startsWith("this.")) {
                        methodCall = getter.substring(5) + "." + methodName;
View Full Code Here

                          getterMethodName = identifier(name.substring(0, openIdx));
                          args = new ExpressionInfo[argExprs.length];
                          argTypes = new GeneratorTypeInfo[argExprs.length];
                          for(int i=0; i < argExprs.length; i++) {
                            String arg = argExprs[i].trim();
                              ExpressionInfo argAccessors = findAccessors(arg, true, false);
                              if (argAccessors == null) {
                                  logger.log(TreeLogger.ERROR, "Couldn't evaluate '" + arg + "' as argument to '" + name + "'", null);
                                  throw new UnableToCompleteException();
                              }
                              args[i] = argAccessors;
                              argTypes[i] = argAccessors.getType();
                          }
                      } else {
                          getterMethodName = identifier(name);
                          args = new ExpressionInfo[0];
                          argTypes = new GeneratorTypeInfo[0];
                      }
                      GeneratorTypeInfo objectType = inType;
                      boolean searchingThis = objectType.equals(myClass);
                      boolean asyncMethod = false;
                      GeneratorMethodInfo getterMethod = null;
                      for(;;) {
                        GeneratorTypeInfo[] syncArgTypesWildcard = new GeneratorTypeInfo[argTypes.length];
                       
                        GeneratorTypeInfo[] asyncArgTypesWildcard = new GeneratorTypeInfo[argTypes.length+1];
                        asyncArgTypesWildcard[argTypes.length] = commonTypes.asyncCallback;
                        GeneratorTypeInfo[] asyncArgTypes = Arrays.copyOf(argTypes, argTypes.length+1);
                        asyncArgTypes[argTypes.length] = commonTypes.asyncCallback;
                       
                        HashSet<String> candidates = new HashSet<String>();
                        candidates.add(getterMethodName);
                        String capGetterMethodName = capitalize(getterMethodName);
              candidates.add("get"+capGetterMethodName);
                        candidates.add("is"+capGetterMethodName);
                        for(String candidate : candidates) {
                          getterMethod = objectType.findMethodMatching(candidate, true, null, argTypes);
                          if(getterMethod == null)
                            getterMethod = objectType.findMethodMatching(candidate, true, null, syncArgTypesWildcard);
                          if(getterMethod != null) {
                            asyncMethod = false;
                            type = getterMethod.getReturnType();
                            break;
                          }
                         
                          if(matchAsync) {
                            getterMethod = objectType.findMethodMatching(candidate, true, null, asyncArgTypes);
                            if(getterMethod == null)
                              getterMethod = objectType.findMethodMatching(candidate, true, null, asyncArgTypesWildcard);
                            if(getterMethod != null) {
                              asyncMethod = true;
                              type = getterMethod.getAsyncReturnType();
                              if(type == null) type = commonTypes.object;
                              break;
                            }
                          }
                        }
                        if(searchingThis && getterMethod == null && objectType instanceof GeneratedInnerClassInfo) {
                            objectType = objectType.getFieldType(PARENT_VIEW_FIELD_NAME, true);
                            if(objectType == null)
                              break;
                            expr = expr+"."+PARENT_VIEW_FIELD_NAME;
                            //System.out.println("Ascending to "+expr+" "+objectType);
                          } else break;
                      }
                      if (getterMethod == null) {
                          logger.log(TreeLogger.ERROR, "findAccessors(): Unable to find a "+(staticAccess?"static":"instance")+" method with the right number of arguments ("
                                          + args.length + (matchAsync?" [ + optional AsyncCallback]":"")+") with name '" + getterMethodName + "' in " + inType
                                          + " for expression '" + path + "'", null);
                          throw new UnableToCompleteException();
                      }
     
                      StringBuffer getterBuf = new StringBuffer();
                      getterBuf.append(expr).append('.').append(getterMethod.getName()).append('(');
                     
                      for (int i = 0; i < args.length; i++) {
                        if(i > 0) getterBuf.append(", ");
                        getterBuf.append(args[i].conversionExpr(getterMethod.getParameterTypes()[i]));
                      }
                     
                      if(asyncMethod) {
                        if(args.length > 0) getterBuf.append(","); // trailing comma for async methods so we can append the callback parameter when we call the method
                      } else getterBuf.append(')');
     
                      getter = getterBuf.toString();
                     
                      asyncGetter = asyncMethod;
                      type = asyncMethod?getterMethod.getAsyncReturnType():getterMethod.getReturnType();
                     
                      // Find the matching setter method (if any).
                      String setterMethodName = getterMethod.getName().replaceFirst("^(is|get)", "set");
                      GeneratorTypeInfo[] setterArgTypes = Arrays.copyOf(argTypes, argTypes.length+1);
                      setterArgTypes[argTypes.length] = type;
                      GeneratorMethodInfo setterMethod = objectType.findMethodMatching(setterMethodName, true, null, setterArgTypes);
                     
                      // If searching for something matching the types we got doesn't work, try it a wildcard for the type
                      if(setterMethod == null) {
                        setterArgTypes = new GeneratorTypeInfo[argTypes.length+1];
                        setterArgTypes[argTypes.length] = type;
                        setterMethod = objectType.findMethodMatching(setterMethodName, true, null, setterArgTypes);
                      }
                     
                      if(setterMethod == null) {
                        setterArgTypes = Arrays.copyOf(argTypes, argTypes.length+2);
                        setterArgTypes[argTypes.length] = type;
                        setterArgTypes[argTypes.length+1] = commonTypes.asyncCallback;
                          setterMethod = objectType.findMethodMatching(setterMethodName, true, PrimitiveTypeInfo.VOID, setterArgTypes);
                          if(setterMethod == null) {
                            setterArgTypes = new GeneratorTypeInfo[argTypes.length+2];
                            setterArgTypes[argTypes.length] = type;
                            setterArgTypes[argTypes.length+1] = commonTypes.asyncCallback;
                              setterMethod = objectType.findMethodMatching(setterMethodName, true, PrimitiveTypeInfo.VOID, setterArgTypes);
                          }
                          if(setterMethod != null)
                            asyncSetter = true;
                      } else {
                        asyncSetter = false;
                      }
            if(setterMethod != null) {
                        StringBuffer setterBuf = new StringBuffer();
                        setterBuf.append(expr).append('.').append(setterMethod.getName()).append('(');
                       
                        for (int i = 0; i < args.length; i++) {
                          if(i > 0) setterBuf.append(", ");
                          String convertedArg = args[i].conversionExpr(setterMethod.getParameterTypes()[i]);
                          if(convertedArg.isEmpty()) {
                            throw new IllegalStateException("Got empty result back from "+args[i]+" converted to "+setterMethod.getParameterTypes()[i]);
                          }
                setterBuf.append(convertedArg);
                        }
                       
                        if(args.length > 0)
                          setterBuf.append(","); // trailing comma for setters so we can append the value parameter and possibly the async callback
       
                        setter = setterBuf.toString();
            }
                } else {
                  // No array or function specifier, so look for a normal property or field
                      String baseExpr = (expr.equals("this") ? "" : expr + ".");
                      name = identifier(name);
                      String getterName = "get" + capitalize(name);
                      String setterName = "set" + capitalize(name);
                      GeneratorMethodInfo getterMethod = inType.findMethodMatching(getterName, true, null);
                      if(getterMethod == null && matchAsync) { // Check for async version, if allowed in this context
                        getterMethod = inType.findMethodMatching(getterName, true, PrimitiveTypeInfo.VOID, commonTypes.asyncCallback);
                        asyncGetter = getterMethod != null;
                      }
                      if (getterMethod == null) {
                          getterName = "is" + capitalize(name);
                          getterMethod = inType.findMethodMatching(getterName, true, null);
                          if(getterMethod == null && matchAsync) { // Check for async version, if allowed in this context
                            getterMethod = inType.findMethodMatching(getterName, true, PrimitiveTypeInfo.VOID, commonTypes.asyncCallback);
                            asyncGetter = getterMethod != null;
                          }
                      }
                      if (getterMethod != null) {
                          getter = baseExpr + getterName + (asyncGetter?"":"()"); // No trailing brackets for an async call
                          if(asyncGetter) {
                            type = getterMethod.getAsyncReturnType();
                            if(type == null) type = commonTypes.object;
                          } else {
                              type = getterMethod.getReturnType();
                          }
                      } else {
                        asyncGetter = false;
                       
                        // Try direct field access
                        type = inType.getFieldType(name, baseExpr.startsWith("this."));
                        if(type != null) {
                          getter = baseExpr + name;
                          setter = baseExpr + name + "=";
                          asyncSetter = false;
                          asyncGetter = false;
                        } else {
                            getter = null;
                        }
                      }
                      if(setter == null) {
                        GeneratorMethodInfo setterMethod;
                        // Only look for the setter if this is the last (or only) part of the chain.  i.e. for an expression
                        // a.b.c we would only look for a setter for c, not a or b.
                        if(lastOrOnlyPartOfTheExpression) {
                          setterMethod = inType.findMethodMatching(setterName, true, null, (GeneratorTypeInfo)null);
                          if(setterMethod == null) {
                              setterMethod = inType.findMethodMatching(setterName, true, PrimitiveTypeInfo.VOID, (GeneratorTypeInfo)null, commonTypes.asyncCallback);
                              asyncSetter = setterMethod != null;
                          }
                          if(setterMethod != null) {
                            //System.out.println("Found setter "+setterMethod);
                              setter = baseExpr + setterName + "(";
                            type = setterMethod.getParameterTypes()[0];
                          }
                        }
                      }
                }
                 
                  //System.out.println("Looking for "+name+" in "+inType+", found "+getter+" and "+setter);
                  if(getter != null && splitPath.length == 2) {
                    if(type.isArray()) {
                      if("length".equals(splitPath[1])) {
                        return new ExpressionInfo(path, getter+"."+splitPath[1], PrimitiveTypeInfo.INT, false);
                      } else {
                            logger.log(TreeLogger.ERROR, "Attempting to access a property of array that I don't recognize: "+getter+"."+splitPath[1], null);
                              throw new UnableToCompleteException();
                      }
                    } else if(type.isPrimitive()) {
                        logger.log(TreeLogger.ERROR, "Attempting to access a property of a primitive type: "+getter+" of type "+type+" async = "+asyncGetter, null);
                          throw new UnableToCompleteException();
                    }
 
                      if(asyncGetter == false) {
                        // Easy... just get them to create a new getter based on this one
                        return findAccessors(new ExpressionInfo(path, getter, type, isConstants(type)), splitPath[1], matchAsync, staticAccess);
                      } else {
                        // Oops, we're getting a property of an async property, time for some magic
                        // The trick: generate a new method that does the first async operation and
                        // then returns the result of the getter of the proceeding attributes.
                        ExpressionInfo subexpr = findAccessors(new ExpressionInfo(path, "base", type, false), splitPath[1], matchAsync, staticAccess);
                        if(subexpr == null) {
                          logger.log(TreeLogger.ERROR, "Failed to find property '"+splitPath[1]+"' of type '"+type+"' of expression '"+getter+"'", null);
                              throw new UnableToCompleteException();
                        }
                        String getterName = "getAsync"+asyncProxies.size();
                        if(subexpr.hasGetter()) {
                            if(subexpr.hasSynchronousGetter()) {
                              // Synchronous sub-expression, how merciful!
                                asyncProxies.add("    public void "+getterName+"(AsyncCallback<Object> callback) {\n"+
                                               "        "+ExpressionInfo.callAsyncGetter(getter, "new AsyncCallbackDirectProxy<Object>(callback, \""+path+"\") {\n"+
                                               "            public void onSuccess(Object result) {\n"+
                                               "                "+type.getParameterizedQualifiedSourceName()+" base = ("+type.getParameterizedQualifiedSourceName()+") result;\n"+
                                               "                returnSuccess("+subexpr.getterExpr()+");\n"+
                                               "            }\n"+
                                               "        }")+";\n"+
                                               "    }\n");
                            } else if(subexpr.hasAsyncGetter()) {
                                asyncProxies.add("    public void "+getterName+"(AsyncCallback<Object> callback) {\n"+
                                  "        "+ExpressionInfo.callAsyncGetter(getter, "new AsyncCallbackDirectProxy<Object>(callback, \""+path+"\") {\n"+
                                  "            public void onSuccess(Object result) {"+
                                  "                "+type.getParameterizedQualifiedSourceName()+" base = ("+type.getParameterizedQualifiedSourceName()+") result;\n"+
                                  "                "+subexpr.callAsyncGetter("callback")+";\n"+
                                  "            }\n"+
                                  "        }")+";\n"+
                                  "    }\n");
                            }
                        } else getterName = null;
                        String setterName = "setAync"+asyncProxies.size();
                        if(subexpr.hasSetter()) {
                            if(subexpr.hasSynchronousSetter()) {
                              // Synchronous sub-expression, how merciful!
                                asyncProxies.add("    public void "+setterName+"(final "+subexpr.getType().getParameterizedQualifiedSourceName()+" value, AsyncCallback<Void> callback) {\n"+
                                     "        "+ExpressionInfo.callAsyncGetter(getter, "new AsyncCallbackDirectProxy<Void>(callback, \""+path+"\") {\n"+
                                               "            public void onSuccess(Void result) {\n"+
                                               "                "+type.getParameterizedQualifiedSourceName()+" base = ("+type.getParameterizedQualifiedSourceName()+") result;\n"+
                                               "                "+subexpr.callSetter("value")+"\n"+
                                               "                returnSuccess(null);\n"+
                                               "            }\n"+
                                      "        }")+";\n"+
                                               "    }");
                            } else if(subexpr.hasAsynchronousSetter()) {
                                asyncProxies.add("    public void "+setterName+"(final "+subexpr.getType().getParameterizedQualifiedSourceName()+" value, AsyncCallback<Void> callback) {\n"+
                                    "        "+ExpressionInfo.callAsyncGetter(getter, "new AsyncCallbackDirectProxy<Void>(callback, \""+path+"\") {\n"+
                                  "            public void onSuccess(Void result) {\n"+
                                  "                "+type.getParameterizedQualifiedSourceName()+" base = ("+type.getParameterizedQualifiedSourceName()+") result;\n"+
                                  "                "+subexpr.callAsyncSetter("value", "callback")+"\n"+
                                  "            }\n"+
                                 "        }")+";\n"+
                                  "    }");
                            }
                        } else setterName = null;
                        return new ExpressionInfo(path, getterName, setterName, subexpr.getType(), true, true, false);
                      }
                  } else if(setter != null && lastOrOnlyPartOfTheExpression) {
                    return new ExpressionInfo(path, getter, setter, type, asyncGetter, asyncSetter, false);
                  }
                 
                  /*
                  JClassType superclass = inType.getSuperclass();
                  if (superclass != null && !ReflectedClassInfo.OBJECT.equals(superclass)) {
                    ExpressionInfo inherited = findAccessors(superclass, expr, path, matchAsync);
                    if(inherited != null) {
                      if(getter == null) {
                        if(inherited.getter != null) { getter = inherited.getter; asyncGetter = false; }
                        else if(inherited.hasAsynchronousGetter()) { getter = inherited.asyncGetter; asyncGetter = true; }
                      }
                      if(setter == null) {
                        if(inherited.hasSynchronousSetter()) { setter = inherited.setter; asyncSetter = false; }
                        else if(inherited.hasAsynchronousSetter()) { setter = inherited.asyncSetter; asyncSetter = true; }
                      }
                      if(type == null) type = inherited.getType();
                    }
                  }
                  */
                  if(type != null) {
                      if((getter != null) && (setter == null) && !asyncGetter
                          && (isConstants(inType))) {
                          //logger.log(TreeLogger.INFO, "Considering value to be constant since it is part of a Constants or DictionaryConstants: "+getter);
                          return new ExpressionInfo(path, getter, type, base.isConstant());
                      } else {
                          return new ExpressionInfo(path, getter, setter, type, asyncGetter, asyncSetter, false);
                      }
                  }
                  //System.out.println("Failed to find property "+name+" on "+inType);
                  return null;
              } finally {
View Full Code Here

                || (operIdx = smartIndexOf(path, "*")) != -1)) {
                return handleBinaryOperator(path, innerType, matchAsync, operIdx);
              } else if(path.startsWith("!") || path.startsWith("not ")) {
                String remainder = path.startsWith("!")?path.substring(1).trim():path.substring(4).trim();               
                //System.out.println("Boolean NOT");                                 
                final ExpressionInfo accessors = findAccessors(remainder, innerType, matchAsync);
                if(accessors != null) {
                  return new ExpressionInfo(accessors, new OperatorInfo() {
                    @Override
              public String onGetExpr(String expr) throws UnableToCompleteException {
                      return "!(" + ExpressionInfo.converter(expr, accessors.getType(), PrimitiveTypeInfo.BOOLEAN) + ')';
                    }
                    @Override
              public String onSetExpr(String expr) throws UnableToCompleteException {
                      return ExpressionInfo.converter("!(" + expr + ')', PrimitiveTypeInfo.BOOLEAN, accessors.getType());
                    }
                  });
                } else {
                  return null;
                }
              } else if(path.startsWith("-") || path.startsWith("~")) {
                String remainder = path.substring(1).trim();
                final String oper = path.substring(0,1);
                ExpressionInfo accessors = findAccessors(remainder, innerType, matchAsync);
                if(accessors != null) {
                  return new ExpressionInfo(accessors, new OperatorInfo() {
                    @Override
              public String onGetExpr(String expr) {
                      return oper + '(' + expr + ')';
                    }
                    @Override
              public String onSetExpr(String expr) {
                      return oper + '(' + expr + ')';
                    }
                  });
                } else {
                  return null;
                }
              } else if(path.length() > 0 && (Character.isDigit(path.charAt(0)) || (path.length() >= 2 && path.charAt(0) == '-' && Character.isDigit(path.charAt(1))))) {
                if(smartIndexOf(path, '.') != -1) {
                  // floating-point
                  return new ExpressionInfo(path, path, JPrimitiveType.DOUBLE, true);
                } else if(path.endsWith("L")) {
                  return new ExpressionInfo(path, path, JPrimitiveType.LONG, true);
                } else {
                  return new ExpressionInfo(path, path, JPrimitiveType.INT, true);
                }
              } else if(path.equals("true") || path.equals("false")) {
                return new ExpressionInfo(path, path, JPrimitiveType.BOOLEAN, true);
              } else if(path.equals("null")) {
                return new ExpressionInfo(path, path, RuntimeClassWrapper.OBJECT, true);
               
              } else if(path.startsWith("\"") && path.endsWith("\"")) {
                return new ExpressionInfo(path, path, getType("java.lang.String"), true);
               
              }
              String thisExpr = innerType ? myClass.getSimpleSourceName() + ".this" : "this";
                GeneratorTypeInfo classToSearch = myClass;
                if (path.equals("this")) {
                  while(classToSearch instanceof GeneratedInnerClassInfo) {
                    classToSearch = ((GeneratedInnerClassInfo)classToSearch).getFieldType(PARENT_VIEW_FIELD_NAME, true);
                    if(classToSearch == null)
                      break;
                    thisExpr = thisExpr+"."+PARENT_VIEW_FIELD_NAME;
                  }
                 
                  // When they use the expression "this", be sure to use the superclass of the generated class;
                  // the generated class won't behave well with isAssignableFrom() and isAssignableTo() because
                  // it's a fake object we created and isn't "known" by the type oracle.
                    return new ExpressionInfo(path, thisExpr, null, classToSearch, false, false, false);
                }
               
                // like books.service.AccountType.ACCOUNTS_RECEIVABLE or abc.def.Foo.bar
                Matcher staticReference = Pattern.compile("([a-z0-9_]+(?:\\.[a-z0-9_]+)+(?:\\.[A-Z][A-Za-z0-9_]+)+)\\.([A-Za-z0-9_]+.*)").matcher(path);
                if(staticReference.matches()) {
                  String className = staticReference.group(1);
                  String property = staticReference.group(2);
                  //System.out.println("Static reference: "+className+" property "+property);
          try {
            JClassType staticType = types.getType(className);
                    JField field = staticType.getField(property);
                    JEnumType enum1 = staticType.isEnum();
                    if(field != null && field.isStatic()) {
              return new ExpressionInfo(path, path, field.getType(), field.isFinal() || enum1!=null);
                    }
                    if(enum1 != null && property.equals("values()")) {
                      return new ExpressionInfo(path, path, types.getArrayType(enum1), true);
                    }
                    return findAccessors(new ExpressionInfo(path, className, staticType, true), property, matchAsync, true);
          } catch (NotFoundException e) {
          } 
                }
               
                for (;;) {
                    ExpressionInfo accessors = findAccessors(new ExpressionInfo(path, thisExpr, classToSearch, true), path, matchAsync, false);
                    if (accessors != null) {
                        return accessors;
                    } else if(classToSearch instanceof GeneratedInnerClassInfo){
                        classToSearch = classToSearch.getFieldType(PARENT_VIEW_FIELD_NAME, true);
                        if (classToSearch == null) {
View Full Code Here

            }

      private ExpressionInfo handleBinaryOperator(String path, boolean innerType, boolean matchAsync, int operIdx)
        throws UnableToCompleteException {
        final String leftPath = path.substring(0, operIdx).trim();
        ExpressionInfo left = findAccessors(leftPath, innerType, matchAsync);
       
        int operLen;
        String oper;
        boolean arithmeticOper=false;
        if(path.startsWith(" or ", operIdx)) {
          operLen = 4;
          oper = "||";
        } else if(path.startsWith(" and ", operIdx)) {
          operLen = 5;
          oper = "&&";
        } else if("+-*/".indexOf(path.charAt(operIdx)) != -1) {
          operLen = 1;
          oper = path.substring(operIdx, operIdx+1);
          arithmeticOper = true;
        } else {
          operLen = 2;
          oper = path.substring(operIdx, operIdx+operLen);
        }
        final String rightPath = path.substring(operIdx+operLen).trim();
        ExpressionInfo right = findAccessors(rightPath, innerType, matchAsync);
        if(left == null || !left.hasGetter()) {
          logger.log(TreeLogger.ERROR, "Can't evaluate "+leftPath+" in "+path+" match async = "+matchAsync, null);
          throw new UnableToCompleteException();
        }
        if(right == null || !right.hasGetter()) {
          logger.log(TreeLogger.ERROR, "Can't evaluate "+rightPath+" in "+path+" match async = "+matchAsync, null);
          throw new UnableToCompleteException();
        }
        GeneratorTypeInfo targetOperandType;
        GeneratorTypeInfo resultType;
        GeneratorTypeInfo java_lang_String = RuntimeClassWrapper.STRING;
        if ("&&".equals(oper) || "||".equals(oper)){
          targetOperandType = PrimitiveTypeInfo.BOOLEAN;
          resultType = PrimitiveTypeInfo.BOOLEAN;
        } else if("+".equals(oper) && (right.getType().getParameterizedQualifiedSourceName().equals("java.lang.String") || left.getType().getParameterizedQualifiedSourceName().equals("java.lang.String"))) {
          targetOperandType = java_lang_String;
          resultType = java_lang_String;
        } else {
          targetOperandType = left.getType();
          if(arithmeticOper)
            resultType = left.getType();
          else // all other operations are boolean
            resultType = PrimitiveTypeInfo.BOOLEAN;
        }
       
        // Is it an asynchronous calculation?
        if(left.hasAsynchronousGetter() || right.hasAsynchronousGetter()) {
          return handleAsyncBinaryOperator(left, oper, right, targetOperandType, resultType);
        }
       
        String convertRight = right.conversionExpr(targetOperandType);
        if(convertRight == null) {
          logger.log(TreeLogger.ERROR, "Can't convert "+right.getType()+" "+right+" to "+targetOperandType, null);
          throw new UnableToCompleteException();
        }
        String convertLeft = left.conversionExpr(targetOperandType);
        if(convertLeft == null) {
          logger.log(TreeLogger.ERROR, "Can't convert "+left+" to "+targetOperandType, null);
          throw new UnableToCompleteException();
        }
        return new ExpressionInfo(path, "(" + convertLeft + oper + convertRight + ")", resultType, left.isConstant() && right.isConstant());
      }
View Full Code Here

TOP

Related Classes of com.habitsoft.kiyaa.rebind.typeinfo.ExpressionInfo

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.