java - 在 Tapestry 5 Web 应用程序中编辑复杂的 Java 对象

标签 java web-applications tapestry rdfstore

我正在将 Tapestry 5.3.6 用于 Web 应用程序,我希望用户使用 Web 表单(立即建议使用 beaneditform) - 但是要编辑的 Java 类具有相当复杂的结构。我正在寻找在 Tapestry 5 中执行此操作的最简单方法。

首先,让我们定义一些实用类,例如

public class ModelObject {
  private URI uri;
  private boolean modified;
  // the usual constructors, getters and setters ...
}

public class Literal<T> extends ModelObject {
  private Class<?> valueClass;
  private T value;
  public Literal(Class<?> valueClass) {
    this.valueClass = valueClass;
  }
  public Literal(Class<?> valueClass, T value) {
    this.valueClass = valueClass;
    this.value = value;
  }
  // the usual getters and setters ...
}

public class Link<T extends ModelObject> extends ModelObject {
  private Class<?> targetClass;
  private T target;
  public Link(Class<?> targetClass) {
    this.targetClass = targetClass;
  }
  public Link(Class<?> targetClass, T target) {
    this.targetClass = targetClass;
    this.target = target;
  }
  // the usual getters and setters ...
}

现在您可以创建一些相当复杂的数据结构,例如:

public class HumanBeing extends ModelObject {
  private Literal<String> name;
  // ... other stuff
  public HumanBeing() {
    name = new Literal<String>(String.class);
  }
  // the usual getters and setters ...
}

public class Project extends ModelObject {
  private Literal<String> projectName;
  private Literal<Date> startDate;
  private Literal<Date> endDate;
  private Literal<Integer> someCounter;
  private Link<HumanBeing> projectLeader;
  private Link<HumanBeing> projectManager;
  // ... other stuff, including lists of things, that may be Literals or
  // Links ... e.g. (ModelObjectList is an enhanced ArrayList that remembers
  // the type(s) of the objects it contains - to get around type erasure ...
  private ModelObjectList<Link<HumanBeing>> projectMembers;
  private ModelObjectList<Link<Project>> relatedProjects;
  private ModelObjectList<Literal<String>> projectAliases;
  // the usual constructors, getters and setters for all of the above ...
  public Project() {
    projectName = new Literal<String>(String.class);
    startDate = new Literal<Date>(Date.class);
    endDate = new Literal<Date>(Date.class);
    someCounter = new Literal<Integer>(Integer.class);
    projectLeader = new Link<HumanBeing>(HumanBeing.class);
    projectManager = new Link<HumanBeing>(HumanBeing.class);
    projectMembers = new ModelObjectList<Link<HumanBeing>>(Link.class, HumanBeing.class);
    // ... more ...
  }
}

如果您将 beaneditform 指向 Project.class 的一个实例,那么在您必须提供大量自定义强制器、翻译器、值编码器等之前,您不会走得太远 - 然后您仍然运行进入当“贡献”所述强制器、翻译器、值编码器等时不能使用泛型的问题。

然后我开始编写自己的组件来解决这些问题(例如 ModelObjectDisplayModelObjectEdit),但这需要我对 Tapestry 有更多的了解比我有时间学习......感觉我可以使用标准组件和自由使用“委托(delegate)”等来做我想做的事。任何人都可以看到一个简单的路径让我采取这个吗?

感谢您阅读到这里。

PS:如果你想知道我为什么做这样的事情,那是因为模型表示来自 RDF 图数据库(又名三重存储)的链接数据 - 我需要记住每一位数据的 URI 以及如何它与其他数据相关(链接)(欢迎您提出更好的方法:-)

编辑:

@uklance 建议使用显示和编辑 block - 这是我已经尝试过的:

首先,我在 AppPropertyDisplayBlocks.tml 中有以下内容......

    <t:block id="literal">
        <t:delegate to="literalType" t:value="literalValue" />
    </t:block>

    <t:block id="link">
        <t:delegate to="linkType" t:value="linkValue" />
    </t:block>

在 AppPropertyDisplayBlocks.java ...

    public Block getLiteralType() {
        Literal<?> literal = (Literal<?>) context.getPropertyValue();

        Class<?> valueClass = literal.getValueClass();
        if (!AppModule.modelTypes.containsKey(valueClass))
            return null;

        String blockId = AppModule.modelTypes.get(valueClass);
        return resources.getBlock(blockId);
    }

    public Object getLiteralValue() {
        Literal<?> literal = (Literal<?>) context.getPropertyValue();
        return literal.getValue();
    }

    public Block getLinkType() {
        Link<?> link = (Link<?>) context.getPropertyValue();

        Class<?> targetClass = link.getTargetClass();
        if (!AppModule.modelTypes.containsKey(targetClass))
            return null;

        String blockId = AppModule.modelTypes.get(targetClass);
        return resources.getBlock(blockId);
    }

    public Object getLinkValue() {
        Link<?> link = (Link<?>) context.getPropertyValue();
        return link.getTarget();
    }

AppModule.modelTypes 是从 java 类到 Tapestry 使用的字符串的映射,例如Link.class -> "link"和 Literal.class -> "literal"...在 AppModule 中我有以下代码 ...

    public static void contributeDefaultDataTypeAnalyzer(
            MappedConfiguration<Class<?>, String> configuration) {
        for (Class<?> type : modelTypes.keySet()) {
            String name = modelTypes.get(type);
            configuration.add(type, name);
        }
    }

    public static void contributeBeanBlockSource(
            Configuration<BeanBlockContribution> configuration) {

        // using HashSet removes duplicates ...
        for (String name : new HashSet<String>(modelTypes.values())) {
            configuration.add(new DisplayBlockContribution(name,
                    "blocks/AppPropertyDisplayBlocks", name));
            configuration.add(new EditBlockContribution(name,
                    "blocks/AppPropertyEditBlocks", name));
        }
    }

我有类似的编辑 block 代码......但是这些似乎都不起作用 - 我认为是因为原始对象被传递给“委托(delegate)”而不是被取消引用的对象,它要么是存储在文字或链接指向的对象(嗯...应该是上面的 [Ll]inkTarget,而不是 [Ll]inkValue)。我也一直遇到 Tapestry 找不到合适的“翻译器”、“值编码器”或“强制器”的错误……我有一些时间压力,所以很难通过这些曲折的 channel 来摆脱困境迷宫:-)

最佳答案

我建议围绕您想要通过 BeanEditForm 编辑的对象构建一个薄包装器并将它们传递给它。所以像这样:

public class TapestryProject {

   private Project project;

   public TapestryProject(Project proj){
      this.project = proj;
   }

   public String getName(){
      this.project.getProjectName().getValue();
   }

   public void setName(String name){
      this.project.getProjectName().setValue(name);
   }

   etc...
}

通过这种方式,Tapestry 将处理它所知道的所有类型,让您不必创建自己的强制转换(顺便说一句,这本身非常简单)。

关于java - 在 Tapestry 5 Web 应用程序中编辑复杂的 Java 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15197597/

相关文章:

java - 如果手动安装 apk,Android 应用程序在真实设备上崩溃

javascript - 库中的 Google Script HTML 表单抛出错误 Uncaught

php - 如何在将链接保存到数据库之前自动在链接前附加 "http://"?

hibernate - 最佳实践 Hibernate 乐观锁定和 Web 应用程序

java - Tapestry 中的表单编码

java - Java Web应用程序框架

Java Applet getImage 给出空指针异常

Java BlackBerry - 如何使用 GET 方法正确调用 php 脚本?

java - 了解在 wait() 中放弃锁

ajax - 定期刷新 Tapestry 区域