Castor (二) -- 自定义映射

1.概述

 

Castor的自定义映射关系通过XML设置。

主要作用有

1)改变映射位置(node): attribute, element, text

2)改变映射名字(name...): attributeName, elementTagName

3)改变层级关系(location)

4)改变输出格式(handler): dateFormat...

5)改变属性获取和设置方式(get/setMethod, direct="true")

6)隐藏属性(auto-complete="true", transient="true")

 

2.源码

 

 Address.java Student.java 详见 Castor (一) -- 默认绑定 

 

LocalDateHandler.java

 

package com.siyuan.castor.handler;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.exolab.castor.mapping.FieldHandler;
import org.exolab.castor.mapping.ValidityException;

import com.siyuan.castor.Student;

public class LocalDateHandler implements FieldHandler {
	
	private static final String LOCAL_DATE_FORMAT = "yyyy-MM-dd";
	
	public void checkValidity(Object object) throws ValidityException,
			IllegalStateException {
	}
	
	/**
	 * @param object the owner of the field
	 */
	public Object getValue(Object object) throws IllegalStateException {
		if (object instanceof Student) {
			Date date = ((Student) object).getBirthday();
			if (date != null) {
				DateFormat dateFmt = new SimpleDateFormat(LOCAL_DATE_FORMAT);
				return dateFmt.format(date);
			} else {
				return null;
			}
		}
		return null;
	}

	public Object newInstance(Object arg0) throws IllegalStateException {
		return null;
	}

	public void resetValue(Object arg0) throws IllegalStateException,
			IllegalArgumentException {
	}
	
	/**
	 * @param object the owner of the field
	 * @param dateString the field value in the xml source file
	 */
	public void setValue(Object object, Object dateString)
			throws IllegalStateException, IllegalArgumentException {
		if (object instanceof Student) {
			DateFormat dateFmt = new SimpleDateFormat(LOCAL_DATE_FORMAT);
			try {
				Date date = dateFmt.parse((String) dateString);
				((Student) object).setBirthday(date);
			} catch (ParseException e) {
				throw new IllegalArgumentException(e);
			}
			
		}
	}

}

 

 DivDateHandler.java

 

package com.siyuan.castor.handler;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.exolab.castor.mapping.GeneralizedFieldHandler;

public class DivDateHandler extends GeneralizedFieldHandler {

	private static final String LOCAL_DATE_FORMAT = "yyyy-MM-dd";
	
	/**
	 * automatically supports iterating over the items of a collection 
	 * and passing them one-by-one to the convertUponGet
	 * 
	 * setCollectionIteration : could modify it
	 */
	public DivDateHandler() {
		setCollectionIteration(false);
	}
	
	/**
	 * @Override
	 * @param value the object value to convert after
                 *  performing a get operation
	 * @return the converted value.
	 */
	public Object convertUponGet(Object value) {
		if (value == null) 
			return null;
		DateFormat dateFmt = new SimpleDateFormat(LOCAL_DATE_FORMAT);
		return dateFmt.format((Date) value);
	}

	/**
	 * @Override
	 * @param value the object value to convert before
                 *  performing a set operation
                 * @return the converted value.
	 */
	public Object convertUponSet(Object value) {
		if (value == null) 
			return null;
		DateFormat dateFmt = new SimpleDateFormat(LOCAL_DATE_FORMAT);
		Date date = null;
		try {
			date = dateFmt.parse((String) value);
		} catch (ParseException e) {
			throw new IllegalArgumentException(e);
		}	
		return date;
	}

	/**
	 * @Override
	 * Returns the class type for the field that this
     	 * GeneralizedFieldHandler converts to and from. This
     	 * should be the type that is used in the
     	 * object model.
     	 *
                 * @return the class type of of the field
	 */
	public Class getFieldType() {
		return Date.class;
	}

}

 

ConfigureDateHandler.java

 

package com.siyuan.castor.handler;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

import org.exolab.castor.mapping.ConfigurableFieldHandler;
import org.exolab.castor.mapping.FieldHandler;
import org.exolab.castor.mapping.ValidityException;

import com.siyuan.castor.Student;

public class ConfigureDateHandler implements FieldHandler,
		ConfigurableFieldHandler {
	
	private static final String DATE_FORMAT_PARAM_NAME = "date-format";
	
	private DateFormat dateFormat;
	
	public void checkValidity(Object arg0) throws ValidityException,
			IllegalStateException {
	}

	public Object getValue(Object object) throws IllegalStateException {
		if (object instanceof Student) {
			Date date = ((Student) object).getBirthday();
			if (date != null) {
				return dateFormat.format(date);
			} else {
				return null;
			}
		}
		return null;
	}

	public Object newInstance(Object arg0) throws IllegalStateException {
		return null;
	}

	public void resetValue(Object arg0) throws IllegalStateException,
			IllegalArgumentException {
	}

	public void setValue(Object object, Object dateString)
			throws IllegalStateException, IllegalArgumentException {
		if (object instanceof Student) {
			try {
				Date date = dateFormat.parse((String) dateString);
				((Student) object).setBirthday(date);
			} catch (ParseException e) {
				throw new IllegalArgumentException(e);
			}
			
		}
	}
	
	/**
	 * @param params configure information in the xml
	 */
	public void setConfiguration(Properties params) throws ValidityException {
		String pattern = params.getProperty(DATE_FORMAT_PARAM_NAME);
		if (pattern == null)
			throw new ValidityException("Required parameter \"" + DATE_FORMAT_PARAM_NAME + "\" is missing");
		try {
			dateFormat = new SimpleDateFormat(pattern);
		} catch (IllegalArgumentException e) {
			throw new ValidityException("Pattern \"" + pattern + "\" is not a valid date format.");
		}
	}

}

 

Student.cst.xml

 

<!DOCTYPE mapping PUBLIC 
"-//EXOLAB/Castor Object Mapping DTD Version 1.0//EN"
"http://castor.exolab.org/mapping.dtd">
<mapping>

	<description>Used for com.siyuan.castor.Student</description>
	
	<!-- 
	<include href=""></include>
	 -->
	 
	<!-- 
	<field-handler />
	 -->
	<field-handler name="localDateHandler" class="com.siyuan.castor.handler.ConfigureDateHandler">
		<param name="date-format" value="yyyy-MM-dd"/>
	</field-handler>
	
	<!-- 
	verify-constructable="false" 
	used with the set-method="%1-9%"
	make it able to omit the no-parameter constructor
	 -->
	<class name="com.siyuan.castor.Student" auto-complete="true">
		
		<description>com.siyuan.castor.Student</description>
		
		<map-to xml="Person"/>
			
		<!-- 
			type="java.lang.String" handler="" required="true" direct="true" transient="true"
			 set-method="%1-9%" get-method="getName" type="string" //can not omit the no-parameter constructor
		-->
		<field name="name">
			<description>property name</description>
      		<bind-xml name="stuName" node="attribute"/>
   		</field>
		
		<!-- 
		type="string" handler="com.siyuan.castor.handler.DivDateHandler" 
		type="string" handler="com.siyuan.castor.handler.LocalDateHandler" 
		//type could not be omitted and must be string
		location="birthday/birthday1"
		-->
		<field name="birthday" type="string" handler="localDateHandler">
      		<bind-xml name="birth" node="attribute"/>
   		</field>
   		
		<field name="friends" collection="set" type="com.siyuan.castor.Student" get-method="getFriends" set-method="addFriend">
      		<bind-xml name="friend" node="element"/>
   		</field>
   		
   		<field name="subjects" collection="arraylist" type="string" get-method="getSubjects" set-method="addSubject">
      		<bind-xml name="subjects" node="element"/>
   		</field>
   		
   		<field name="teachers" collection="map">
      		<bind-xml name="teachers" node="element">
	      		<class name="org.exolab.castor.mapping.MapItem">
	      			<field name="key" type="java.lang.String">
	      				<bind-xml name="name" node="attribute"/>
	      			</field>
	      			<field name="value" type="java.lang.String">
	      				<bind-xml name="subject" node="attribute"/>
	      			</field>
	      		</class>
      		</bind-xml>
   		</field>
   		
	</class>
	
	<!-- not used for XML mapping
	<key-generator />
	 -->
	
</mapping> 

 

CastorDIYTest.java

 

package com.siyuan.castor.test;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.mapping.MappingException;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.Marshaller;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.ValidationException;
import org.xml.sax.InputSource;

import com.siyuan.castor.Address;
import com.siyuan.castor.Student;

public class CastorDIYTest {

	/**
	 * @param args
	 * @throws ValidationException 
	 * @throws MarshalException 
	 * @throws ValidationException 
	 * @throws MarshalException 
	 */
	public static void main(String[] args) throws MarshalException, ValidationException{
		Student stuSrc = new Student();
		stuSrc.setAge(22);
		stuSrc.setName("SingleMan");
		stuSrc.setMale(true);
		Address address = new Address();
		address.setStreet("Renmin Road");
		stuSrc.setAddress(address);
		DateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd");
		try {
			Date birthday = dateFmt.parse("1988-11-21");
			stuSrc.setBirthday(birthday);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		
		Student girl = new Student();
		girl.setAge(20);
		stuSrc.setGirlFriend(girl);
		
		Set<Student> students = new HashSet<Student>();
		Student stu1 = new Student();
		stu1.setAge(21);
		students.add(stu1);
		Student stu2 = new Student();
		stu2.setAge(23);
		students.add(stu2);
		
		stuSrc.addFriend(stu1);
		stuSrc.addFriend(stu2);
		
		stuSrc.addSubject("English");
		stuSrc.addSubject("Math");
		stuSrc.addSubject("Chinese");
		
		Map<String, String> teachers = new HashMap<String, String>();
		teachers.put("English", "teacher a");
		teachers.put("Math", "teacher b");
		teachers.put("Chinese", "teacher c");
		stuSrc.setTeachers(teachers);
		
		Mapping mapping = new Mapping();
		try {
			InputStream mappingFileIn = Student.class
				.getResourceAsStream("/com/siyuan/castor/Student.cst.xml");
			mapping.loadMapping(new InputSource(mappingFileIn));
			
			StringWriter result = new StringWriter();

			Marshaller marshaller = new Marshaller();
			marshaller.setMapping(mapping);
			marshaller.setWriter(result);
			marshaller.marshal(stuSrc);
			System.out.println(result);
			
			System.out.println("=================================================================");
			
			Unmarshaller unmarshaller = new Unmarshaller(mapping);
			Student stuDist = (Student) unmarshaller.unmarshal(new StringReader(result.toString()));
			System.out.println(stuDist);
			
		} catch (MappingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

 

3. 输出结果

 

<?xml version="1.0" encoding="UTF-8"?>
<Person stuName="SingleMan" birth="1988-11-21" male="true" age="22"><friend male="false" age="23"/><friend male="false" age="21"/><subjects>English</subjects><subjects>Math</subjects><subjects>Chinese</subjects><teachers name="English" subject="teacher a"/><teachers name="Math" subject="teacher b"/><teachers name="Chinese" subject="teacher c"/><girl-friend male="false" age="20"/><address><street>Renmin Road</street></address></Person>
=================================================================
Student[name=SingleMan,age=22,male=true,birthday=Mon Nov 21 00:00:00 CST 1988,
address=Address[street=Renmin Road],
girlFriend=Student[name=null,age=20,male=false,birthday=null,
address=null,
girlFriend=null,
friends=[],
subjects=[],
teachers={}
],
friends=[Student[name=null,age=23,male=false,birthday=null,
address=null,
girlFriend=null,
friends=[],
subjects=[],
teachers={}
], Student[name=null,age=21,male=false,birthday=null,
address=null,
girlFriend=null,
friends=[],
subjects=[],
teachers={}
]],
subjects=[English, Math, Chinese],
teachers={English=teacher a, Math=teacher b, Chinese=teacher c}
]

 

 

4.参考资料

 

http://www.castor.org/xml-mapping.html

 

http://www.castor.org/xml-fieldhandlers.html#Use-ConfigurableFieldHandler-for-more-flexibility

 

附件为mapping文件对应的DTD和XSD文件

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值