// Ensures that embed bound properties are writable
  private void checkEmbedAgainst(
      PageCompilingContext pc,
      EvaluatorCompiler compiler,
      Map<String, String> properties,
      Class<?> embedClass,
      Node node) {

    // TODO also type check them against expressions
    for (String property : properties.keySet()) {
      try {
        if (!compiler.isWritable(property)) {
          pc.errors.add(
              CompileError.in(node.outerHtml())
                  // TODO we need better line number detection if there is whitespace between the
                  // annotation and tag.
                  .near(node.siblingIndex() - 1) // TODO -  line number of the annotation
                  .causedBy(
                      CompileErrors.PROPERTY_NOT_WRITEABLE,
                      String.format(
                          "Property %s#%s was not writable. Did you forget to create "
                              + "a setter or @Visible annotation?",
                          embedClass.getSimpleName(), property)));
        }
      } catch (ExpressionCompileException ece) {
        pc.errors.add(
            CompileError.in(node.outerHtml())
                .near(node.siblingIndex()) // TODO - line number
                .causedBy(CompileErrors.ERROR_COMPILING_PROPERTY));
      }
    }
  }
  private Map<String, Type> parseRepeatScope(PageCompilingContext pc, String[] extract, Node node) {
    RepeatToken repeat = registry.parseRepeat(extract[1]);
    Map<String, Type> context = Maps.newHashMap();

    // Verify that @Repeat was parsed correctly.
    if (null == repeat.var()) {
      pc.errors.add(
          CompileError.in(node.outerHtml())
              .near(node.siblingIndex()) // TODO - line number
              .causedBy(CompileErrors.MISSING_REPEAT_VAR));
    }
    if (null == repeat.items()) {
      pc.errors.add(
          CompileError.in(node.outerHtml())
              .near(node.siblingIndex()) // TODO  - line number
              .causedBy(CompileErrors.MISSING_REPEAT_ITEMS));
    }

    try {
      Type egressType = pc.lexicalScopes.peek().resolveEgressType(repeat.items());

      // convert to collection if we need to
      Type elementType;
      Class<?> egressClass = Generics.erase(egressType);
      if (egressClass.isArray()) {
        elementType = Generics.getArrayComponentType(egressType);
      } else if (Collection.class.isAssignableFrom(egressClass)) {
        elementType =
            Generics.getTypeParameter(egressType, Collection.class.getTypeParameters()[0]);
      } else {
        pc.errors.add(
            CompileError.in(node.outerHtml())
                .near(node.siblingIndex()) // TODO - line number
                .causedBy(CompileErrors.REPEAT_OVER_ATOM));
        return Collections.emptyMap();
      }

      context.put(repeat.var(), elementType);
      context.put(repeat.pageVar(), pc.page);
      context.put("__page", pc.page);
      context.put("index", int.class);
      context.put("isLast", boolean.class);

    } catch (ExpressionCompileException e) {
      pc.errors.add(
          CompileError.in(node.outerHtml())
              .near(node.siblingIndex()) // TODO - line number
              .causedBy(e));
    }

    return context;
  }
  private void checkFormFields(PageCompilingContext pc, Node element) {
    if (null == pc.form) return;

    String action = pc.form.attr("action");

    // Only look at contextual uris (i.e. hosted by us).
    // TODO - relative, not starting with '/'
    if (null == action || (!action.startsWith("/"))) return;

    final PageBook.Page page = pageBook.get(action);

    // Only look at pages we actually have registered.
    if (null == page) {
      pc.warnings.add(
          CompileError.in(element.outerHtml())
              .near(line(element))
              .causedBy(CompileErrors.UNRESOLVABLE_FORM_ACTION));

      return;
    }

    // If we're inside a form do a throw-away compile against the target page.
    if ("input".equals(element.nodeName()) || "textarea".equals(element.nodeName())) {
      String name = element.attr("name");

      // Skip submits and buttons.
      if (skippable(element.attr("type"))) return;

      // TODO Skip empty?
      if (null == name) {
        pc.warnings.add(
            CompileError.in(element.outerHtml())
                .near(line(element))
                .causedBy(CompileErrors.FORM_MISSING_NAME));

        return;
      }

      // Compile expression path.
      try {
        new MvelEvaluatorCompiler(page.pageClass()).compile(name);

      } catch (ExpressionCompileException e) {
        // TODO Very hacky, needed to strip out xmlns attribution.
        pc.warnings.add(
            CompileError.in(element.outerHtml())
                .near(element.siblingIndex()) // TODO - line number
                .causedBy(CompileErrors.UNRESOLVABLE_FORM_BINDING, e));
      }
    }
  }
  private static String cleanHtml(final Node node) {
    if (node instanceof Element) {
      Element element = ((Element) node);
      StringBuilder accum = new StringBuilder();
      accum.append("<").append(element.tagName());
      for (Attribute attribute : element.attributes()) {
        if (!(attribute.getKey().startsWith("_"))) {
          accum.append(" ");
          accum.append(attribute.getKey());
          accum.append("=\"");
          accum.append(attribute.getValue());
          accum.append('"');
        }
      }

      if (element.childNodes().isEmpty() && element.tag().isEmpty()) {
        accum.append(" />");
      } else {
        accum.append(">");
        for (Node child : element.childNodes()) accum.append(cleanHtml(child));

        accum.append("</").append(element.tagName()).append(">");
      }
      return accum.toString();
    } else if (node instanceof TextNode) {
      return ((TextNode) node).getWholeText();
    } else if (node instanceof XmlDeclaration) {

      // HACK
      if (node.childNodes().isEmpty()) {
        return "";
      }
      return node.outerHtml();
    } else if (node instanceof Comment) {
      // HACK: elide comments for now.
      return "";
    } else if (node instanceof DataNode && node.childNodes().isEmpty()) {
      // No child nodes are defined but we have to handle content if such exists, example
      // <script language="JavaScript">var a =  { name: "${user.name}"}</script>

      String content = node.attr("data");
      if (Strings.empty(content)) {
        return "";
      }

      return content;
    } else {
      return node.outerHtml();
    }
  }
Example #5
0
 public static String outerHtml(Node node) {
   if (htmlCache.containsKey(node)) {
     return htmlCache.get(node);
   }
   String html = node.outerHtml();
   if (htmlCache.size() == MAX_HTML_CACHE) {
     htmlCache.clear();
   }
   htmlCache.put(node, html);
   return html;
 }
  // hit when the node is first seen
  public void head(Node node, int depth) {
    String name = node.nodeName();
    if (name.equals("li")) append('\n');
    else if (node.toString().startsWith("<select")) {
      append1("[SELECT]");
      append(tab);
    } else if (node.outerHtml().startsWith("<option")) {
      // append1(node.attr("value")+":");append1(" ");
      TextNodeVisitor textVisitor = new TextNodeVisitor();
      node.traverse(textVisitor);
      append1("{" + textVisitor.toString() + "}");

    } else if (node.outerHtml().startsWith("<input")) {
      if (node.attr("type").equals("input")) append1("[INPUT]" + node.attr("maxLength"));
    } else if (node.outerHtml().startsWith("<span")) {
      TextNodeVisitor textVisitor = new TextNodeVisitor();
      node.traverse(textVisitor);
      append1(":" + textVisitor.toString() + " ");
    }
  }
Example #7
0
  public Map<String, String> attempt(Element element) {
    Map<String, String> attributes = new HashMap<String, String>();
    for (Entry<String, Matcher> entry : matchers.entrySet()) {
      if (entry.getValue().test(element)) {
        attributes.put(entry.getKey(), decode(element.text()));
      }
    }

    for (Entry<String, Matcher> entry : textMatchers.entrySet()) {
      if (entry.getValue().test(element)) {
        Node textNode = element.nextSibling();
        if (null != textNode) {
          attributes.put(entry.getKey(), decode(textNode.outerHtml()));
        }
      }
    }

    for (Entry<String, Matcher> entry : subtextMatchers.entrySet()) {
      if (entry.getValue().test(element)) {
        TextNode textNode = element.textNodes().get(0);
        if (null != textNode) {
          attributes.put(entry.getKey(), decode(textNode.outerHtml()));
        }
      }
    }

    for (Entry<String, Matcher> entry : htmlMatchers.entrySet()) {
      if (entry.getValue().test(element)) {
        attributes.put(entry.getKey(), element.html());
      }
    }

    for (Entry<String, Matcher> entry : ptextMatchers.entrySet()) {
      if (entry.getValue().test(element)) {
        attributes.put(entry.getKey(), plainTextFormatter.getPlainText(element));
      }
    }

    for (Entry<String, Object[]> entry : attrMatchers.entrySet()) {
      Object[] objects = entry.getValue();
      Matcher matcher = (Matcher) objects[0];
      String attr = (String) objects[1];
      if (matcher.test(element)) {
        attributes.put(entry.getKey(), element.attr(attr));
      }
    }
    return attributes;
  }
  private void checkUriConsistency(PageCompilingContext pc, Node element) {
    String uriAttrib = element.attr("action");
    if (null == uriAttrib) uriAttrib = element.attr("src");
    if (null == uriAttrib) uriAttrib = element.attr("href");

    if (null != uriAttrib) {

      // Verify that such a uri exists in the page book,
      // only if it is contextual--ignore abs & relative URIs.
      if (uriAttrib.startsWith("/"))
        if (null == pageBook.nonCompilingGet(uriAttrib))
          pc.warnings.add(
              CompileError.in(element.outerHtml())
                  .near(element.siblingIndex()) // TODO - line number
                  .causedBy(CompileErrors.UNRESOLVABLE_FORM_ACTION, uriAttrib));
    }
  }
Example #9
0
 /**
  * Get the outer HTML of this node.
  *
  * @return HTML
  */
 public String outerHtml() {
   StringBuilder accum = new StringBuilder(32 * 1024);
   outerHtml(accum);
   return accum.toString();
 }
Example #10
0
 private void html(StringBuilder accum) {
   for (Node node : childNodes) node.outerHtml(accum);
 }