论坛首页 Java企业应用论坛

SModel- 提供 XML , JSON , POJO 等结构化数据统一编程模型

浏览 8312 次
精华帖 (1) :: 良好帖 (4) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-09-08   最后修改:2009-12-20
最近几月在闲暇时做了一款针对结构化模型查询及编辑的开源框架,大家可以在 http://code.google.com/p/smodel/得到相应源码及文档.

欢迎大家批评指正!

下载地址: http://smodel.googlecode.com/files/smodel-1.0.2-bin-dependencies.jar

源码: http://smodel.googlecode.com/files/smodel-1.0.2-src.jar

源码SVN:http://smodel.googlecode.com/svn/trunk/

SModel provides users a uniform way to access and manipulate structured model in the format of XML, JSON, POJO or other user defined data format from data source such as stream, database or others.

Base on SModel, Document Oriented Service(DOS) framework can employee a uniform set of APIs to read and manipulate different format of document.

Features
1) provides a uniform way to access and manipulate structure model, including: add, remove, query, move, update, and introspect data. SModel also provides mechanism to subscribe for the change event of the model manipulation.
2)supports to load model from XML, JSON, POJO, or user defined format.
3)supports to flush model to XML, JSON, POJO or user defined format.
4)supports to validate model according to SModel defined or user defined rule.
5)provides mechanism to extend the function of the model.
6)provides mechanism to subscribe for error or warning message of the SModel.

Two Minutes Reference
1)create a xml document
sample xml:
        <?xml version="1.0" encoding="UTF-8"?>
        <order id="order id 1" name="order name 1">
            <orderDate>2009-09-06 20:36:01.196</orderDate>
            <items>
                <item count="100" id="item id 1" name="item name 1" price="10.3" />
            </items>
        </order>

IXmlModel orderModel = new XmlModel("order");
      orderModel.setProperty("id", "order id 1");
      orderModel.setProperty("name", "order name 1");
      orderModel.setChildText("orderDate", Utils.buildTimestamp(new Timestamp(new Date().getTime())));
                
      IXmlModel items = (IXmlModel) orderModel.addChild("items");
      IXmlModel item = (IXmlModel) items.addChild("item");
      item.setProperty("id", "item id 1");
      item.setProperty("name", "item name 1");
      item.setProperty("price", 10.3);
      item.setProperty("count", 100);
                
      XmlModelService.flushToXml(orderModel, "d:/order.xml");

2)load from xml document
IXmlModel orderModel = XmlModelService.loadFromXml(new FileReader("d:/order.xml"));

3)create a json document
sample json:
{"order":
  {"$tag":"order",
    "items":
     {"item":
       {"$tag":"item",
        "$attr":{"price":"10.3","name":"item name 1","count":"100","id":"item id 1"}
       },
       "$tag":"items"
     },
     "orderDate":"2009-09-06 21:42:25.603",
     "$attr":{"name":"order name 1","id":"order id 1"}
  }
}

"$tag" and "$attr" are the kept words for JSON to XML mapping.

 //initialize orderModel
      IXmlModel orderModel= ...

      XmlModelService.flushToJson(orderModel, new FileWriter("d:/order.json"));

4)load from json document
IXmlModel orderModel = XmlModelService.loadFromJson(new FileReader("d:/order.json"));

5)flush to POJO
public class Order {
        private String id;
        private String name; 
        private Timestamp orderDate;
        private List<Item> items = Utils.newList();
        // ... default constructor and getter/setter methods
        //for the array field(items in this case), setter method is not mandatory if the add method exists
        //SModel(1.0.0) support the kind of array field includes:Object[],List,Set
    }

    public class Item {
        private String id;
        private String name;
        private double price;
        private int count;       
        // ... default constructor and getter/setter methods
    }     

       //define POJO channel
        BeanModelChannel orderChannel = new BeanModelChannel(Order.class, "order");
        orderChannel.propertyAsAttribute("id");
        orderChannel.propertyAsAttribute("name");
        orderChannel.propertyAsChildText("orderDate");
        
        BeanModelChannel itemChannel = new BeanModelChannel(Item.class, "item");
        itemChannel.propertyAsAttribute("id");
        itemChannel.propertyAsAttribute("name");
        itemChannel.propertyAsAttribute("price");
        itemChannel.propertyAsAttribute("count");
                
        orderChannel.arrayPropertyAs(itemChannel);
 

        //initialize orderModel
        IXmlModel orderModel = ...

        //flush to POJO
        Order order = (Order) XmlModelService.flushToBean(orderModel, orderChannel);

6)load from POJO
    Order order = ...//prepare POJO
    IXmlModel orderModel = XmlModelService.loadFromBean(order, orderChannel);

7)query model
//get first items/item element
IXmlModel itemModel = (IXmlModel) orderModel.queryFirstTreeChild("items/item");

//get the first element of items/item whose price equal 10.3
List<ITreeModel> itemModes = orderModel.queryTreeChild("items/item{price=10.3}[0]")

//get the element which price is more expensive than 10.3
Query priceQuery = new Query();
priceQuery.addExpression(new IExpression(){
    public boolean isMatched(IModel model) {
        double price = model.getDoubleProperty("price");
        return price > 10.3;
    }
});

List<ITreeModel> itemModels = orderModel.getTreeChild(NameHelper.buildFullName("items", "item"), priceQuery);

8)manipulate model
//change the order name to "order new name"
orderModel.setProperty("name", "order new name");

//set order date to "2009-09-07 20:36:01.196"
orderModel.setChildText("orderDate", "2009-09-07 20:36:01.196");

//add a new item
Map<String, Object> propValPairs = Utils.newMap();
propValPairs.put("id", "item id 2");
propValPairs.put("name", "item name 2");
propValPairs.put("count", "100");
propValPairs.put("price", 10.4);
orderModel.addChild("items/item", propValPairs); 

//move the index 1 of the items/item to index 0
orderModel.moveTreeChild("items/item", 1, 0);

//delete the item whose price is equal to 10.4
orderModel.removeTreeChild("items/item", Query.valueOf("price=10.4"));

9)introspect model attribute
int count = itemModel.getIntProperty("count", 0);
double price = itemModel.getDoubleProperty("price", 0.0);
     
//CustomizedClass is String, Boolean, Byte, Short, Integer, 
//Double, BigDecimal, BigInteger, URI, Date, Timestamp 
//and the class has the static method "public static Object valueOf(String str)" defined.
itemModel.getTypedProperty("id", CustomizedClass.class, defaultValue);

 
//get a typed value by employing a valueFactory
itemModel.getTypedProperty("id",
                            new IValueFactory<CustomizeObject>(){
                                public CustomizeObject valueOf(String value) {
                                     return new CustomizeObject(value);
                                }
                            }, 
                            defaultValue);

10)validate model
XmlModelDefinition orderModelDefinition = XmlModelDefinition.createDefaultXmlModelDefinition("root", null);

//the attribute id and name of element items/item is mandantory
orderModelDefinition.installRule(new PropertyMandantoryRule("items/item", IModelRule.SEVERITY_ERROR, "id", "name"));

//the count of items/item should at least be one
orderModelDefinition.installRule(new ChildCountRule(IModelRule.SEVERITY_ERROR, "items/item", ChildCountRule.ONE_TO_MANY));

ValidationResult validateRlt = orderModel.validate(orderModelDefinition); 
boolean isValid = validateRlt.isValid();
List<String> errMsgs = validateRlt.getErrMsgs();
   发表时间:2009-09-09  
SModel提供一套便利的模型访问与操纵框架,可以方便的实现诸如XML 与 JSON, XML 与 POJO,JSON 与POJO之间的互相转换。

下面以XML 到 JSON 的转换为例:
1)准备好XML,如放在d:/order.xml。
2)从XML装载模型
IXmlModel orderModel = XmlModelService.loadFromXml(new FileReader("d:/order.xml"));
装载好模型之后我们可以利用SModel提供的API,进行模型编辑。
3)将模型导出为JSON
XmlModelService.flushToJson(orderModel, new FileWriter("d:/order.json"));
 
0 请登录后投票
   发表时间:2009-09-09  
jsonlib xstream 等工具类!!!
0 请登录后投票
   发表时间:2009-09-09   最后修改:2009-09-09
SModel旨在提供结构化模型查询,编辑,校验的一套框架。
至于数据展现形式如JSON,XML,POJO,或用户自定义格式,仅仅是模型序列化与反序列化的数据载体而已。
SModel并不是简单的Json或xml操纵工具。SModel提供针对结构化模型编辑的API才是其强调的重点。
0 请登录后投票
   发表时间:2009-09-10  
SModel的适用场景是什么?因为LZ举得例子中,不管Json、XML还是POJO,他们的结构都是一样的,不太实用。

撇开这个功能,其实LZ应该类似JCR的模型了,JCR中是Node+Property,和LZ的差不多。

基于这种模型,如何搞定前台和后台才可能是大家想要的。不过这套模型搞定View和Dao容易,怕就怕Service,我要从中获取几个属性来处理业务逻辑时,难免要写node.getProperty("xxx");这种代码,这种代码的维护成本很高的。
0 请登录后投票
   发表时间:2009-09-10   最后修改:2009-09-10
SModel原用于基于文档的服务框架如Spring-WS,用来处理Xml,JSON格式的文档数据查询,编辑,校验。

我们在处理中发现,不管是XML,JSON都能够使用一套结构化模型去表示,用统一的一套API去访问操作,发觉是很有必要的一件事情。

另外基于文档的形式传输数据,用node.getProperty或node.getIntProperty或node.getTypedProperty是一件很正常的处理方式。

当然有时候对于文档我们已有成熟的Value Object(POJO)去表示,可以通过SModel提供的映射机制,完成模型到POJO的映射。

至于你提到的xml,JSON,POJO的结构一致的疑问,在SModel里XML到POJO的不同结构映射是支持的。对于JSON与XML目前还没有做映射支持,不过JSON与XML在实际应用场合中仅仅是对同一套数据模型的两种表达方式,不同元素映射不是很强的要求,因而在SModel1.0.0没有做支持。
0 请登录后投票
   发表时间:2009-09-11  
总感觉java的工具太多,学起来挺累的。类似smodel这样的工具我觉得很好,至少只用学一遍。
0 请登录后投票
   发表时间:2009-09-13  
SModel has updated to smodel-1.0.1.
Comparing to 1.0.0, it make following changes:

1. enable IModel cloneable.
2. XML load and flush use Mode Source and Model Channel mechanism.
3. simplify the IModelSource and ModelLoader
0 请登录后投票
   发表时间:2009-09-13  
感觉很少会遇到这几种东西的互相转换 尤其是xml和json功能是基本相同的不太会在同一个模块并存 而他们与pojo的转换操作已经有很好的工具了
0 请登录后投票
   发表时间:2009-09-14   最后修改:2009-09-14
beckrabbit 写道
感觉很少会遇到这几种东西的互相转换 尤其是xml和json功能是基本相同的不太会在同一个模块并存 而他们与pojo的转换操作已经有很好的工具了


SModel是为xml,json,pojo之间的互相转换提供了支持,这是其架构决定了其实现的便利性。在开放式API的系统中,如校内,淘宝网,可以很容易使用SModel完成向客户端发送不同格式数据的目的。

但smodel并不仅仅是这样一个互相转换的工具,其生命力我想应该除了这个模型格式转换外,更应该在其对模型数据的生成,检索,更新,校验方面。我曾经想使用SDO,看了一下SDO的API,发觉比较杂乱,因而smodel应该是一个类似SDO,我自己心目中的SDO。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics