Java tutorial
/* * Copyright 2008-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.guzz.builder; import java.io.IOException; import java.io.InputStream; import java.util.LinkedList; import java.util.List; import java.util.Properties; import org.apache.xerces.impl.Constants; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.Visitor; import org.dom4j.VisitorSupport; import org.dom4j.io.SAXReader; import org.guzz.GuzzContextImpl; import org.guzz.connection.DBGroup; import org.guzz.exception.GuzzException; import org.guzz.id.Configurable; import org.guzz.id.IdentifierGenerator; import org.guzz.id.IdentifierGeneratorFactory; import org.guzz.orm.Business; import org.guzz.orm.BusinessInterpreter; import org.guzz.orm.CustomTableView; import org.guzz.orm.ShadowTableView; import org.guzz.orm.mapping.ObjectMappingUtil; import org.guzz.orm.mapping.POJOBasedObjectMapping; import org.guzz.orm.rdms.SimpleTable; import org.guzz.orm.rdms.TableColumn; import org.guzz.util.Assert; import org.guzz.util.ClassUtil; import org.guzz.util.StringUtil; import org.guzz.util.javabean.BeanCreator; import org.guzz.util.javabean.BeanWrapper; import org.guzz.util.javabean.JavaBeanWrapper; import org.guzz.web.context.GuzzContextAware; import org.xml.sax.SAXException; /** * * parse hbm.xml formatting orm. * * @author liukaixuan(liukaixuan@gmail.com) */ public class HbmXMLBuilder { public static String getDomainClassName(Element root) throws DocumentException, IOException, SAXException { String packageName = root.attributeValue("package"); List bus = root.selectNodes("//class"); if (bus == null) return null; if (bus.size() != 1) { throw new DocumentException("too many class name"); } Element e = (Element) bus.get(0); String className = e.attributeValue("name"); if (StringUtil.notEmpty(packageName)) { className = packageName + "." + className; } return className; } public static String getDomainClassBusinessName(Element root) throws DocumentException, IOException, SAXException { List bus = root.selectNodes("//class"); if (bus == null) return null; if (bus.size() != 1) { throw new DocumentException("too many class name"); } Element e = (Element) bus.get(0); return e.attributeValue("businessName"); } public static String getDomainClassDbGroup(Element root) throws DocumentException, IOException, SAXException { List bus = root.selectNodes("//class"); if (bus == null) return null; if (bus.size() != 1) { throw new DocumentException("too many class name"); } Element e = (Element) bus.get(0); return e.attributeValue("dbGroup"); } public static POJOBasedObjectMapping parseHbmStream(final GuzzContextImpl gf, String dbGroupName, BusinessValidChecker checker, String businessName, Class overridedDomainClass, Class interpreterClass, InputStream is) throws DocumentException, IOException, SAXException, ClassNotFoundException { SAXReader reader = null; Document document = null; reader = new SAXReader(); reader.setValidation(false); // http://apache.org/xml/features/nonvalidating/load-external-dtd" reader.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE, false); document = reader.read(is); final Element root = document.getRootElement(); if (StringUtil.isEmpty(dbGroupName)) { dbGroupName = getDomainClassDbGroup(root); } if (StringUtil.isEmpty(dbGroupName)) { dbGroupName = "default"; } final DBGroup dbGroup = gf.getDBGroup(dbGroupName); final SimpleTable st = new SimpleTable(dbGroup.getDialect()); final POJOBasedObjectMapping map = new POJOBasedObjectMapping(gf, dbGroup, st); if (overridedDomainClass == null) {//hbm?className String m_class = HbmXMLBuilder.getDomainClassName(root); overridedDomainClass = ClassUtil.getClass(m_class); } if (checker != null && !checker.shouldParse(overridedDomainClass)) { return null; } if (StringUtil.isEmpty(businessName)) { businessName = getDomainClassBusinessName(root); } final Business business = gf.instanceNewGhost(businessName, dbGroup.getGroupName(), interpreterClass, overridedDomainClass); if (business.getInterpret() == null) { throw new GuzzException("cann't create new instance of business: " + business.getName()); } business.setTable(st); business.setMapping(map); //?business?? if (business.getName() != null) { st.setBusinessName(business.getName()); } else { st.setBusinessName(business.getDomainClass().getName()); } //properties defined. final LinkedList props = new LinkedList(); Visitor visitor = new VisitorSupport() { private String packageName; public void visit(Element e) { //package if ("hibernate-mapping".equalsIgnoreCase(e.getName()) || "guzz-mapping".equalsIgnoreCase(e.getName())) { this.packageName = e.attributeValue("package"); } else if ("class".equalsIgnoreCase(e.getName())) { String className = e.attributeValue("name"); String tableName = e.attributeValue("table"); String shadow = e.attributeValue("shadow"); boolean dynamicUpdate = StringUtil.toBoolean(e.attributeValue("dynamic-update"), false); if (StringUtil.notEmpty(this.packageName)) { className = this.packageName + "." + className; } //business????hbml.xml?class namebusinessclass Class cls = business.getDomainClass(); if (cls == null) { //?business?domainClassName cls = ClassUtil.getClass(className); } Assert.assertNotNull(cls, "invalid class name"); Assert.assertNotEmpty(tableName, "invalid table name"); JavaBeanWrapper configBeanWrapper = BeanWrapper.createPOJOWrapper(cls); business.setDomainClass(cls); business.setConfiguredBeanWrapper(configBeanWrapper); map.setBusiness(business); //shadow?tableName? if (StringUtil.notEmpty(shadow)) { ShadowTableView sv = (ShadowTableView) BeanCreator.newBeanInstance(shadow); sv.setConfiguredTableName(tableName); //CustomTableViewShadowTableView if (sv instanceof CustomTableView) { CustomTableView ctv = (CustomTableView) sv; ctv.setConfiguredObjectMapping(map); st.setCustomTableView(ctv); } st.setShadowTableView(sv); gf.registerShadowTableView(sv); } //TODO: ??? st.setTableName(tableName); st.setDynamicUpdate(dynamicUpdate); } else if ("id".equalsIgnoreCase(e.getName())) { String name = e.attributeValue("name"); String type = e.attributeValue("type"); String column = null; Element columnE = (Element) e.selectSingleNode("column"); if (columnE != null) { column = columnE.attributeValue("name"); } if (StringUtil.isEmpty(column)) { column = e.attributeValue("column"); } if (StringUtil.isEmpty(column)) { column = name; } props.addLast(name); TableColumn col = ObjectMappingUtil.createTableColumn(gf, map, name, column, type, null); st.addPKColumn(col); } else if ("version".equalsIgnoreCase(e.getName())) { //see: http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/mapping.html 5.1.9. Version (optional) //TODO: annotation?version? String name = e.attributeValue("name"); String type = e.attributeValue("type"); boolean insertIt = StringUtil.toBoolean(e.attributeValue("insert"), true); String column = null; Element columnE = (Element) e.selectSingleNode("column"); if (columnE != null) { column = columnE.attributeValue("name"); } if (StringUtil.isEmpty(column)) { column = e.attributeValue("column"); } if (StringUtil.isEmpty(column)) { column = name; } props.addLast(name); TableColumn col = ObjectMappingUtil.createTableColumn(gf, map, name, column, type, null); col.setAllowInsert(insertIt); st.addVersionColumn(col); } else if ("property".equalsIgnoreCase(e.getName())) { String name = e.attributeValue("name"); String type = e.attributeValue("type"); String nullValue = e.attributeValue("null"); String lazy = e.attributeValue("lazy"); String loader = e.attributeValue("loader"); boolean insertIt = StringUtil.toBoolean(e.attributeValue("insert"), true); boolean updateIt = StringUtil.toBoolean(e.attributeValue("update"), true); String column = null; Element columnE = (Element) e.selectSingleNode("column"); if (columnE != null) { column = columnE.attributeValue("name"); } if (StringUtil.isEmpty(column)) { column = e.attributeValue("column"); } if (StringUtil.isEmpty(column)) { column = name; } props.addLast(name); TableColumn col = ObjectMappingUtil.createTableColumn(gf, map, name, column, type, loader); col.setNullValue(nullValue); col.setAllowInsert(insertIt); col.setAllowUpdate(updateIt); col.setLazy("true".equalsIgnoreCase(lazy)); st.addColumn(col); } } }; root.accept(visitor); //?generator //?generator? List generator = root.selectNodes("//class/id/generator"); if (generator.size() != 1) { throw new GuzzException("id generator is not found for business: " + business); } Element ge = (Element) generator.get(0); String m_clsName = ge.attributeValue("class"); if ("native".equalsIgnoreCase(m_clsName)) { //nativegeneratordialect? m_clsName = dbGroup.getDialect().getNativeIDGenerator(); } String realClassName = (String) IdentifierGeneratorFactory.getGeneratorClass(m_clsName); if (realClassName == null) { realClassName = m_clsName; } IdentifierGenerator ig = (IdentifierGenerator) BeanCreator.newBeanInstance(realClassName); //?generator?? List m_params = ge.selectNodes("param"); Properties p = new Properties(); for (int i = 0; i < m_params.size(); i++) { Element mp = (Element) m_params.get(i); p.put(mp.attributeValue("name"), mp.getTextTrim()); } if (ig instanceof Configurable) { ((Configurable) ig).configure(dbGroup.getDialect(), map, p); } //register callback for GuzzContext's full starting. if (ig instanceof GuzzContextAware) { gf.registerContextStartedAware((GuzzContextAware) ig); } st.setIdentifierGenerator(ig); return map; } /** * ???? {@link POJOBasedObjectMapping} * * <p/>? {@link BusinessInterpreter} , {@link IdentifierGenerator} ?? * ???????? */ public static interface BusinessValidChecker { /** * @return true ?false null */ public boolean shouldParse(Class domainClass); } }