示例#1
0
  public void configureTemplateMessage(final String from, final String subject) {
    final String contextPath = getApplicationContextPath();
    final Document document = XmlUtils.readXml(fileManager.getInputStream(contextPath));
    final Element root = document.getDocumentElement();

    final Map<String, String> props = new HashMap<String, String>();

    if (StringUtils.hasText(from) || StringUtils.hasText(subject)) {
      Element smmBean = getSimpleMailMessageBean(root);
      if (smmBean == null) {
        smmBean = document.createElement("bean");
        smmBean.setAttribute("class", "org.springframework.mail.SimpleMailMessage");
        smmBean.setAttribute("id", "templateMessage");
      }

      if (StringUtils.hasText(from)) {
        Element smmProperty = XmlUtils.findFirstElement("//property[@name='from']", smmBean);
        if (smmProperty != null) {
          smmBean.removeChild(smmProperty);
        }
        smmProperty = document.createElement("property");
        smmProperty.setAttribute("value", "${email.from}");
        smmProperty.setAttribute("name", "from");
        smmBean.appendChild(smmProperty);
        props.put("email.from", from);
      }

      if (StringUtils.hasText(subject)) {
        Element smmProperty = XmlUtils.findFirstElement("//property[@name='subject']", smmBean);
        if (smmProperty != null) {
          smmBean.removeChild(smmProperty);
        }
        smmProperty = document.createElement("property");
        smmProperty.setAttribute("value", "${email.subject}");
        smmProperty.setAttribute("name", "subject");
        smmBean.appendChild(smmProperty);
        props.put("email.subject", subject);
      }

      root.appendChild(smmBean);

      DomUtils.removeTextNodes(root);

      fileManager.createOrUpdateTextFileIfRequired(
          contextPath, XmlUtils.nodeToString(document), false);
    }

    if (props.size() > 0) {
      propFileOperations.addProperties(
          Path.SPRING_CONFIG_ROOT, "email.properties", props, true, true);
    }
  }
  public Database getDatabase(final boolean evictCache) {
    if (!evictCache && cachedIntrospections.contains(lastDatabase)) {
      for (Database database : cachedIntrospections) {
        if (database.equals(lastDatabase)) {
          return lastDatabase;
        }
      }
    }
    if (evictCache && cachedIntrospections.contains(lastDatabase)) {
      cachedIntrospections.remove(lastDatabase);
    }

    String dbreXmlPath = getDbreXmlPath();
    if (!StringUtils.hasText(dbreXmlPath) || !fileManager.exists(dbreXmlPath)) {
      return null;
    }

    Database database = null;
    InputStream inputStream = null;
    try {
      inputStream = fileManager.getInputStream(dbreXmlPath);
      database = DatabaseXmlUtils.readDatabase(inputStream);
      cacheDatabase(database);
      return database;
    } catch (Exception e) {
      throw new IllegalStateException(e);
    } finally {
      IOUtils.closeQuietly(inputStream);
    }
  }
示例#3
0
  private String getDateTimeFormat() {
    String format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_SHORT)";
    if (annotations == null || annotations.isEmpty()) {
      return format;
    }

    String style = "";
    AnnotationMetadata annotation =
        MemberFindingUtils.getAnnotationOfType(annotations, DATE_TIME_FORMAT);
    if (annotation != null) {
      AnnotationAttributeValue<?> attr = annotation.getAttribute(new JavaSymbolName("style"));
      if (attr != null) {
        style = (String) attr.getValue();
      }
    }
    if (StringUtils.hasText(style)) {
      if (style.equals("S")) {
        format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_TIME_SHORT)";
      } else if (style.equals("M")) {
        format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_TIME_MEDIUM)";
      } else if (style.equals("F")) {
        format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_TIME_FULL)";
      } else if (style.equals("S-")) {
        format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_SHORT)";
      } else if (style.equals("M-")) {
        format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_MEDIUM)";
      } else if (style.equals("F-")) {
        format = "DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_FULL)";
      }
    }
    return format;
  }
  /**
   * Locates the entity manager field that should be used.
   *
   * <p>If a parent is defined, it must provide the field.
   *
   * <p>We generally expect the field to be named "entityManager" and be of type
   * javax.persistence.EntityManager. We also require it to be public or protected, and annotated
   * with @PersistenceContext. If there is an existing field which doesn't meet these latter
   * requirements, we add an underscore prefix to the "entityManager" name and try again, until such
   * time as we come up with a unique name that either meets the requirements or the name is not
   * used and we will create it.
   *
   * @return the entity manager field (never returns null)
   */
  public FieldMetadata getEntityManagerField() {
    if (parent != null) {
      // The parent is required to guarantee this is available
      return parent.getEntityManagerField();
    }

    // Need to locate it ourself
    int index = -1;
    while (true) {
      // Compute the required field name
      index++;
      final JavaSymbolName fieldSymbolName =
          new JavaSymbolName(StringUtils.repeat("_", index) + "entityManager");
      final FieldMetadata candidate = governorTypeDetails.getField(fieldSymbolName);
      if (candidate != null) {
        // Verify if candidate is suitable

        if (!Modifier.isPublic(candidate.getModifier())
            && !Modifier.isProtected(candidate.getModifier())
            && (Modifier.TRANSIENT != candidate.getModifier())) {
          // Candidate is not public and not protected and not simply a transient field (in which
          // case subclasses
          // will see the inherited field), so any subsequent subclasses won't be able to see it.
          // Give up!
          continue;
        }

        if (!candidate.getFieldType().equals(ENTITY_MANAGER)) {
          // Candidate isn't an EntityManager, so give up
          continue;
        }

        if (MemberFindingUtils.getAnnotationOfType(candidate.getAnnotations(), PERSISTENCE_CONTEXT)
            == null) {
          // Candidate doesn't have a PersistenceContext annotation, so give up
          continue;
        }

        // If we got this far, we found a valid candidate
        return candidate;
      }

      // Candidate not found, so let's create one
      final List<AnnotationMetadataBuilder> annotations =
          new ArrayList<AnnotationMetadataBuilder>();
      final AnnotationMetadataBuilder annotationBuilder =
          new AnnotationMetadataBuilder(PERSISTENCE_CONTEXT);
      if (StringUtils.hasText(crudAnnotationValues.getPersistenceUnit())) {
        annotationBuilder.addStringAttribute("unitName", crudAnnotationValues.getPersistenceUnit());
      }
      annotations.add(annotationBuilder);

      final FieldMetadataBuilder fieldBuilder =
          new FieldMetadataBuilder(
              getId(), Modifier.TRANSIENT, annotations, fieldSymbolName, ENTITY_MANAGER);
      return fieldBuilder.build();
    }
  }
 public boolean supportsSchema(final boolean displayAddOns) throws RuntimeException {
   Connection connection = null;
   try {
     connection = getConnection(displayAddOns);
     DatabaseMetaData databaseMetaData = connection.getMetaData();
     String schemaTerm = databaseMetaData.getSchemaTerm();
     return StringUtils.hasText(schemaTerm) && schemaTerm.equalsIgnoreCase("schema");
   } catch (Exception e) {
     throw new IllegalStateException(e);
   } finally {
     connectionProvider.closeConnection(connection);
   }
 }
 private void addTransactionalAnnotation(
     final List<AnnotationMetadataBuilder> annotations, final boolean isPersistMethod) {
   final AnnotationMetadataBuilder transactionalBuilder =
       new AnnotationMetadataBuilder(TRANSACTIONAL);
   if (StringUtils.hasText(crudAnnotationValues.getTransactionManager())) {
     transactionalBuilder.addStringAttribute(
         "value", crudAnnotationValues.getTransactionManager());
   }
   if (isGaeEnabled && isPersistMethod) {
     transactionalBuilder.addEnumAttribute(
         "propagation", new EnumDetails(PROPAGATION, new JavaSymbolName("REQUIRES_NEW")));
   }
   annotations.add(transactionalBuilder);
 }
  private Connection getConnection(final boolean displayAddOns) {
    final String dbProps = "database.properties";
    final String jndiDataSource = getJndiDataSourceName();
    if (StringUtils.hasText(jndiDataSource)) {
      Map<String, String> props =
          propFileOperations.getProperties(
              Path.SPRING_CONFIG_ROOT.getModulePathId(projectOperations.getFocusedModuleName()),
              "jndi.properties");
      return connectionProvider.getConnectionViaJndiDataSource(
          jndiDataSource, props, displayAddOns);
    } else if (fileManager.exists(
        projectOperations
            .getPathResolver()
            .getFocusedIdentifier(Path.SPRING_CONFIG_ROOT, dbProps))) {
      Map<String, String> props =
          propFileOperations.getProperties(
              Path.SPRING_CONFIG_ROOT.getModulePathId(projectOperations.getFocusedModuleName()),
              dbProps);
      return connectionProvider.getConnection(props, displayAddOns);
    }

    Properties connectionProperties = getConnectionPropertiesFromDataNucleusConfiguration();
    return connectionProvider.getConnection(connectionProperties, displayAddOns);
  }
  /** @return a test for the persist method, if available and requested (may return null) */
  private MethodMetadataBuilder getRemoveMethodTest(
      final MemberTypeAdditions removeMethod,
      final MemberTypeAdditions findMethod,
      final MemberTypeAdditions flushMethod,
      final MethodMetadata identifierAccessorMethod) {
    if (!annotationValues.isRemove()
        || removeMethod == null
        || findMethod == null
        || identifierAccessorMethod == null) {
      // User does not want this method or one of its core dependencies
      return null;
    }

    // Prepare method signature
    JavaSymbolName methodName =
        new JavaSymbolName("test" + StringUtils.capitalize(removeMethod.getMethodName()));
    if (governorHasMethod(methodName)) {
      return null;
    }

    builder.getImportRegistrationResolver().addImport(identifierAccessorMethod.getReturnType());

    List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
    annotations.add(new AnnotationMetadataBuilder(TEST));
    if (isGaeSupported) {
      AnnotationMetadataBuilder transactionalBuilder = new AnnotationMetadataBuilder(TRANSACTIONAL);
      if (StringUtils.hasText(transactionManager)
          && !"transactionManager".equals(transactionManager)) {
        transactionalBuilder.addStringAttribute("value", transactionManager);
      }
      transactionalBuilder.addEnumAttribute(
          "propagation", new EnumDetails(PROPAGATION, new JavaSymbolName("SUPPORTS")));
      annotations.add(transactionalBuilder);
    }

    final String entityName = annotationValues.getEntity().getSimpleTypeName();

    InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
    bodyBuilder.appendFormalLine(
        entityName
            + " obj = dod."
            + dataOnDemandMetadata.getRandomPersistentEntityMethod().getMethodName().getSymbolName()
            + "();");
    bodyBuilder.appendFormalLine(
        "Assert.assertNotNull(\"Data on demand for '"
            + entityName
            + "' failed to initialize correctly\", obj);");
    bodyBuilder.appendFormalLine(
        identifierAccessorMethod.getReturnType().getSimpleTypeName()
            + " id = obj."
            + identifierAccessorMethod.getMethodName().getSymbolName()
            + "();");
    bodyBuilder.appendFormalLine(
        "Assert.assertNotNull(\"Data on demand for '"
            + entityName
            + "' failed to provide an identifier\", id);");
    bodyBuilder.appendFormalLine("obj = " + findMethod.getMethodCall() + ";");
    bodyBuilder.appendFormalLine(removeMethod.getMethodCall() + ";");

    if (flushMethod != null) {
      bodyBuilder.appendFormalLine(flushMethod.getMethodCall() + ";");
      flushMethod.copyAdditionsTo(builder, governorTypeDetails);
    }

    bodyBuilder.appendFormalLine(
        "Assert.assertNull(\"Failed to remove '"
            + entityName
            + "' with identifier '\" + id + \"'\", "
            + findMethod.getMethodCall()
            + ");");

    removeMethod.copyAdditionsTo(builder, governorTypeDetails);
    findMethod.copyAdditionsTo(builder, governorTypeDetails);

    MethodMetadataBuilder methodBuilder =
        new MethodMetadataBuilder(
            getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE, bodyBuilder);
    methodBuilder.setAnnotations(annotations);
    return methodBuilder;
  }
  /** Adds the JUnit and Spring type level annotations if needed */
  private void addRequiredIntegrationTestClassIntroductions(final JavaType dodGovernor) {
    // Add an @RunWith(SpringJunit4ClassRunner) annotation to the type, if
    // the user did not define it on the governor directly
    if (MemberFindingUtils.getAnnotationOfType(governorTypeDetails.getAnnotations(), RUN_WITH)
        == null) {
      AnnotationMetadataBuilder runWithBuilder = new AnnotationMetadataBuilder(RUN_WITH);
      runWithBuilder.addClassAttribute(
          "value", "org.springframework.test.context.junit4.SpringJUnit4ClassRunner");
      builder.addAnnotation(runWithBuilder);
    }

    // Add an @ContextConfiguration("classpath:/applicationContext.xml")
    // annotation to the type, if the user did not define it on the governor
    // directly
    if (MemberFindingUtils.getAnnotationOfType(
            governorTypeDetails.getAnnotations(), CONTEXT_CONFIGURATION)
        == null) {
      AnnotationMetadataBuilder contextConfigurationBuilder =
          new AnnotationMetadataBuilder(CONTEXT_CONFIGURATION);
      contextConfigurationBuilder.addStringAttribute(
          "locations", "classpath:/META-INF/spring/applicationContext*.xml");
      builder.addAnnotation(contextConfigurationBuilder);
    }

    // Add an @Transactional, if the user did not define it on the governor
    // directly
    if (annotationValues.isTransactional()
        && MemberFindingUtils.getAnnotationOfType(
                governorTypeDetails.getAnnotations(), TRANSACTIONAL)
            == null) {
      AnnotationMetadataBuilder transactionalBuilder = new AnnotationMetadataBuilder(TRANSACTIONAL);
      if (StringUtils.hasText(transactionManager)
          && !"transactionManager".equals(transactionManager)) {
        transactionalBuilder.addStringAttribute("value", transactionManager);
      }
      builder.addAnnotation(transactionalBuilder);
    }

    // Add the data on demand field if the user did not define it on the
    // governor directly
    FieldMetadata field = governorTypeDetails.getField(new JavaSymbolName("dod"));
    if (field != null) {
      Assert.isTrue(
          field.getFieldType().equals(dodGovernor),
          "Field 'dod' on '"
              + destination.getFullyQualifiedTypeName()
              + "' must be of type '"
              + dodGovernor.getFullyQualifiedTypeName()
              + "'");
      Assert.notNull(
          MemberFindingUtils.getAnnotationOfType(field.getAnnotations(), AUTOWIRED),
          "Field 'dod' on '"
              + destination.getFullyQualifiedTypeName()
              + "' must be annotated with @Autowired");
    } else {
      // Add the field via the ITD
      List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
      annotations.add(new AnnotationMetadataBuilder(AUTOWIRED));
      FieldMetadataBuilder fieldBuilder =
          new FieldMetadataBuilder(
              getId(), Modifier.PRIVATE, annotations, new JavaSymbolName("dod"), dodGovernor);
      builder.addField(fieldBuilder);
    }

    builder.getImportRegistrationResolver().addImport(ASSERT);
  }
示例#10
0
  public void installEmail(
      final String hostServer,
      final MailProtocol protocol,
      final String port,
      final String encoding,
      final String username,
      final String password) {
    Assert.hasText(hostServer, "Host server name required");

    final String contextPath = getApplicationContextPath();
    final Document document = XmlUtils.readXml(fileManager.getInputStream(contextPath));
    final Element root = document.getDocumentElement();

    boolean installDependencies = true;
    final Map<String, String> props = new HashMap<String, String>();

    Element mailBean =
        XmlUtils.findFirstElement(
            "/beans/bean[@class = 'org.springframework.mail.javamail.JavaMailSenderImpl']", root);
    if (mailBean != null) {
      root.removeChild(mailBean);
      installDependencies = false;
    }

    mailBean = document.createElement("bean");
    mailBean.setAttribute("class", "org.springframework.mail.javamail.JavaMailSenderImpl");
    mailBean.setAttribute("id", "mailSender");

    final Element property = document.createElement("property");
    property.setAttribute("name", "host");
    property.setAttribute("value", "${email.host}");
    mailBean.appendChild(property);
    root.appendChild(mailBean);
    props.put("email.host", hostServer);

    if (protocol != null) {
      final Element pElement = document.createElement("property");
      pElement.setAttribute("value", "${email.protocol}");
      pElement.setAttribute("name", "protocol");
      mailBean.appendChild(pElement);
      props.put("email.protocol", protocol.getProtocol());
    }

    if (StringUtils.hasText(port)) {
      final Element pElement = document.createElement("property");
      pElement.setAttribute("name", "port");
      pElement.setAttribute("value", "${email.port}");
      mailBean.appendChild(pElement);
      props.put("email.port", port);
    }

    if (StringUtils.hasText(encoding)) {
      final Element pElement = document.createElement("property");
      pElement.setAttribute("name", "defaultEncoding");
      pElement.setAttribute("value", "${email.encoding}");
      mailBean.appendChild(pElement);
      props.put("email.encoding", encoding);
    }

    if (StringUtils.hasText(username)) {
      final Element pElement = document.createElement("property");
      pElement.setAttribute("name", "username");
      pElement.setAttribute("value", "${email.username}");
      mailBean.appendChild(pElement);
      props.put("email.username", username);
    }

    if (StringUtils.hasText(password)) {
      final Element pElement = document.createElement("property");
      pElement.setAttribute("name", "password");
      pElement.setAttribute("value", "${email.password}");
      mailBean.appendChild(pElement);
      props.put("email.password", password);

      if (SMTP.equals(protocol)) {
        final Element javaMailProperties = document.createElement("property");
        javaMailProperties.setAttribute("name", "javaMailProperties");
        final Element securityProps = document.createElement("props");
        javaMailProperties.appendChild(securityProps);
        final Element prop = document.createElement("prop");
        prop.setAttribute("key", "mail.smtp.auth");
        prop.setTextContent("true");
        securityProps.appendChild(prop);
        final Element prop2 = document.createElement("prop");
        prop2.setAttribute("key", "mail.smtp.starttls.enable");
        prop2.setTextContent("true");
        securityProps.appendChild(prop2);
        mailBean.appendChild(javaMailProperties);
      }
    }

    DomUtils.removeTextNodes(root);

    fileManager.createOrUpdateTextFileIfRequired(
        contextPath, XmlUtils.nodeToString(document), false);

    if (installDependencies) {
      updateConfiguration();
    }

    propFileOperations.addProperties(
        Path.SPRING_CONFIG_ROOT, "email.properties", props, true, true);
  }
示例#11
0
  /**
   * Generates the "send email" method to be added to the domain type
   *
   * @param mailSenderName the name of the MailSender field (required)
   * @param async whether to send the email asynchronously
   * @param targetClassMID the MID of the class to receive the method
   * @param mutableTypeDetails the type to which the method is being added (required)
   * @return a non-<code>null</code> method
   */
  private MethodMetadata getSendMethod(
      final JavaSymbolName mailSenderName,
      final boolean async,
      final String targetClassMID,
      final ClassOrInterfaceTypeDetailsBuilder classOrInterfaceTypeDetailsBuilder) {
    final String contextPath = getApplicationContextPath();
    final Document document = XmlUtils.readXml(fileManager.getInputStream(contextPath));
    final Element root = document.getDocumentElement();

    // Make a builder for the created method's body
    final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();

    // Collect the types and names of the created method's parameters
    final PairList<AnnotatedJavaType, JavaSymbolName> parameters =
        new PairList<AnnotatedJavaType, JavaSymbolName>();

    if (getSimpleMailMessageBean(root) == null) {
      // There's no SimpleMailMessage bean; use a local variable
      bodyBuilder.appendFormalLine(
          "org.springframework.mail.SimpleMailMessage "
              + LOCAL_MESSAGE_VARIABLE
              + " = new org.springframework.mail.SimpleMailMessage();");
      // Set the from address
      parameters.add(STRING, new JavaSymbolName("mailFrom"));
      bodyBuilder.appendFormalLine(LOCAL_MESSAGE_VARIABLE + ".setFrom(mailFrom);");
      // Set the subject
      parameters.add(STRING, new JavaSymbolName("subject"));
      bodyBuilder.appendFormalLine(LOCAL_MESSAGE_VARIABLE + ".setSubject(subject);");
    } else {
      // A SimpleMailMessage bean exists; auto-wire it into the entity and use it as a template
      final List<AnnotationMetadataBuilder> smmAnnotations =
          Arrays.asList(new AnnotationMetadataBuilder(AUTOWIRED));
      final FieldMetadataBuilder smmFieldBuilder =
          new FieldMetadataBuilder(
              targetClassMID,
              PRIVATE_TRANSIENT,
              smmAnnotations,
              new JavaSymbolName(TEMPLATE_MESSAGE_FIELD),
              SIMPLE_MAIL_MESSAGE);
      classOrInterfaceTypeDetailsBuilder.addField(smmFieldBuilder.build());
      // Use the injected bean as a template (for thread safety)
      bodyBuilder.appendFormalLine(
          "org.springframework.mail.SimpleMailMessage "
              + LOCAL_MESSAGE_VARIABLE
              + " = new org.springframework.mail.SimpleMailMessage("
              + TEMPLATE_MESSAGE_FIELD
              + ");");
    }

    // Set the to address
    parameters.add(STRING, new JavaSymbolName("mailTo"));
    bodyBuilder.appendFormalLine(LOCAL_MESSAGE_VARIABLE + ".setTo(mailTo);");

    // Set the message body
    parameters.add(STRING, new JavaSymbolName("message"));
    bodyBuilder.appendFormalLine(LOCAL_MESSAGE_VARIABLE + ".setText(message);");

    bodyBuilder.newLine();
    bodyBuilder.appendFormalLine(mailSenderName + ".send(" + LOCAL_MESSAGE_VARIABLE + ");");

    final MethodMetadataBuilder methodBuilder =
        new MethodMetadataBuilder(
            targetClassMID,
            Modifier.PUBLIC,
            new JavaSymbolName("sendMessage"),
            JavaType.VOID_PRIMITIVE,
            parameters.getKeys(),
            parameters.getValues(),
            bodyBuilder);

    if (async) {
      if (DomUtils.findFirstElementByName("task:annotation-driven", root) == null) {
        // Add asynchronous email support to the application
        if (!StringUtils.hasText(root.getAttribute("xmlns:task"))) {
          // Add the "task" namespace to the Spring config file
          root.setAttribute("xmlns:task", SPRING_TASK_NS);
          root.setAttribute(
              "xsi:schemaLocation",
              root.getAttribute("xsi:schemaLocation")
                  + "  "
                  + SPRING_TASK_NS
                  + " "
                  + SPRING_TASK_XSD);
        }
        root.appendChild(
            new XmlElementBuilder("task:annotation-driven", document)
                .addAttribute("executor", "asyncExecutor")
                .addAttribute("mode", "aspectj")
                .build());
        root.appendChild(
            new XmlElementBuilder("task:executor", document)
                .addAttribute("id", "asyncExecutor")
                .addAttribute("pool-size", "${executor.poolSize}")
                .build());
        // Write out the new Spring config file
        fileManager.createOrUpdateTextFileIfRequired(
            contextPath, XmlUtils.nodeToString(document), false);
        // Update the email properties file
        propFileOperations.addPropertyIfNotExists(
            Path.SPRING_CONFIG_ROOT, "email.properties", "executor.poolSize", "10", true);
      }
      methodBuilder.addAnnotation(new AnnotationMetadataBuilder(ASYNC));
    }
    return methodBuilder.build();
  }
  public MetadataItem get(String metadataIdentificationString) {
    ProjectMetadata projectMetadata = projectOperations.getProjectMetadata();
    if (projectMetadata == null) {
      return null;
    }

    ClassOrInterfaceTypeDetails proxy = getGovernor(metadataIdentificationString);
    if (proxy == null) {
      return null;
    }

    AnnotationMetadata proxyAnnotation =
        GwtUtils.getFirstAnnotation(proxy, GwtUtils.PROXY_ANNOTATIONS);
    if (proxyAnnotation == null) {
      return null;
    }

    String locatorType = GwtUtils.getStringValue(proxyAnnotation.getAttribute("locator"));
    if (!StringUtils.hasText(locatorType)) {
      return null;
    }

    ClassOrInterfaceTypeDetails entity = gwtTypeService.lookupEntityFromProxy(proxy);
    if (entity == null) {
      return null;
    }

    MethodMetadata idAccessor = persistenceMemberLocator.getIdentifierAccessor(entity.getName());
    MethodMetadata versionAccessor = persistenceMemberLocator.getVersionAccessor(entity.getName());
    if (idAccessor == null || versionAccessor == null) {
      return null;
    }

    final JavaType idType = GwtUtils.convertPrimitiveType(idAccessor.getReturnType(), true);
    String locatorIdentifier = PhysicalTypeIdentifier.createIdentifier(new JavaType(locatorType));
    ClassOrInterfaceTypeDetailsBuilder locatorBuilder =
        new ClassOrInterfaceTypeDetailsBuilder(locatorIdentifier);
    AnnotationMetadataBuilder annotationMetadataBuilder =
        new AnnotationMetadataBuilder(RooJavaType.ROO_GWT_LOCATOR);
    annotationMetadataBuilder.addStringAttribute(
        "value", entity.getName().getFullyQualifiedTypeName());
    locatorBuilder.addAnnotation(annotationMetadataBuilder);
    annotationMetadataBuilder = new AnnotationMetadataBuilder(SpringJavaType.COMPONENT);
    locatorBuilder.addAnnotation(annotationMetadataBuilder);
    locatorBuilder.setName(new JavaType(locatorType));
    locatorBuilder.setModifier(Modifier.PUBLIC);
    locatorBuilder.setPhysicalTypeCategory(PhysicalTypeCategory.CLASS);
    locatorBuilder.addExtendsTypes(
        new JavaType(
            GwtUtils.LOCATOR.getFullyQualifiedTypeName(),
            0,
            DataType.TYPE,
            null,
            Arrays.asList(entity.getName(), idType)));
    locatorBuilder.addMethod(getCreateMethod(locatorIdentifier, entity.getName()));
    locatorBuilder.addMethod(
        getFindMethod(locatorBuilder, locatorIdentifier, entity.getName(), idType));
    locatorBuilder.addMethod(getDomainTypeMethod(locatorIdentifier, entity.getName()));
    locatorBuilder.addMethod(getIdMethod(locatorIdentifier, entity.getName(), idAccessor));
    locatorBuilder.addMethod(getIdTypeMethod(locatorIdentifier, entity.getName(), idType));
    locatorBuilder.addMethod(
        getVersionMethod(locatorIdentifier, entity.getName(), versionAccessor));

    typeManagementService.createOrUpdateTypeOnDisk(locatorBuilder.build());
    return null;
  }
  private String getJpaQuery(
      List<Token> tokens,
      String simpleTypeName,
      JavaSymbolName finderName,
      String plural,
      String entityName) {
    String typeName = StringUtils.hasText(entityName) ? entityName : simpleTypeName;
    StringBuilder builder = new StringBuilder();
    builder.append("SELECT o FROM ").append(typeName);
    builder.append(" AS o WHERE ");

    FieldToken lastFieldToken = null;
    boolean isNewField = true;
    boolean isFieldApplied = false;

    for (Token token : tokens) {
      if (token instanceof ReservedToken) {
        String reservedToken = token.getValue();
        if (lastFieldToken == null) continue;
        String fieldName = lastFieldToken.getField().getFieldName().getSymbolName();
        boolean setField = true;

        if (!lastFieldToken.getField().getFieldType().isCommonCollectionType()) {
          if (isNewField) {
            if (reservedToken.equalsIgnoreCase("Like")) {
              builder.append("LOWER(").append("o.").append(fieldName).append(')');
            } else {
              builder.append("o.").append(fieldName);
            }
            isNewField = false;
            isFieldApplied = false;
          }
          if (reservedToken.equalsIgnoreCase("And")) {
            if (!isFieldApplied) {
              builder.append(" = :").append(fieldName);
              isFieldApplied = true;
            }
            builder.append(" AND ");
            setField = false;
          } else if (reservedToken.equalsIgnoreCase("Or")) {
            if (!isFieldApplied) {
              builder.append(" = :").append(fieldName);
              isFieldApplied = true;
            }
            builder.append(" OR ");
            setField = false;
          } else if (reservedToken.equalsIgnoreCase("Between")) {
            builder
                .append(" BETWEEN ")
                .append(":min")
                .append(
                    lastFieldToken.getField().getFieldName().getSymbolNameCapitalisedFirstLetter())
                .append(" AND ")
                .append(":max")
                .append(
                    lastFieldToken.getField().getFieldName().getSymbolNameCapitalisedFirstLetter())
                .append(" ");
            setField = false;
            isFieldApplied = true;
          } else if (reservedToken.equalsIgnoreCase("Like")) {
            builder.append(" LIKE ");
            setField = true;
          } else if (reservedToken.equalsIgnoreCase("IsNotNull")) {
            builder.append(" IS NOT NULL ");
            setField = false;
            isFieldApplied = true;
          } else if (reservedToken.equalsIgnoreCase("IsNull")) {
            builder.append(" IS NULL ");
            setField = false;
            isFieldApplied = true;
          } else if (reservedToken.equalsIgnoreCase("Not")) {
            builder.append(" IS NOT ");
          } else if (reservedToken.equalsIgnoreCase("NotEquals")) {
            builder.append(" != ");
          } else if (reservedToken.equalsIgnoreCase("LessThan")) {
            builder.append(" < ");
          } else if (reservedToken.equalsIgnoreCase("LessThanEquals")) {
            builder.append(" <= ");
          } else if (reservedToken.equalsIgnoreCase("GreaterThan")) {
            builder.append(" > ");
          } else if (reservedToken.equalsIgnoreCase("GreaterThanEquals")) {
            builder.append(" >= ");
          } else if (reservedToken.equalsIgnoreCase("Equals")) {
            builder.append(" = ");
          }
          if (setField) {
            if (builder.toString().endsWith("LIKE ")) {
              builder.append("LOWER(:").append(fieldName).append(") ");
            } else {
              builder.append(':').append(fieldName).append(' ');
            }
            isFieldApplied = true;
          }
        }
      } else {
        lastFieldToken = (FieldToken) token;
        isNewField = true;
      }
    }
    if (isNewField) {
      if (lastFieldToken != null
          && !lastFieldToken.getField().getFieldType().isCommonCollectionType()) {
        builder.append("o.").append(lastFieldToken.getField().getFieldName().getSymbolName());
      }
      isFieldApplied = false;
    }
    if (!isFieldApplied) {
      if (lastFieldToken != null
          && !lastFieldToken.getField().getFieldType().isCommonCollectionType()) {
        builder.append(" = :").append(lastFieldToken.getField().getFieldName().getSymbolName());
      }
    }
    return builder.toString().trim();
  }