Java tutorial
/* * Copyright 2009 The Corner Team. * * 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 corner.tree.services.impl; import java.sql.SQLException; import java.util.List; import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import org.springframework.orm.hibernate3.HibernateCallback; import corner.orm.hibernate.HibernateEntityService; import corner.orm.services.EntityService; import corner.tree.base.TreeAdapter; /** * ? * * @author <a href="mailto:jun.tsai@ganshane.net">Jun Tsai</a> * @version $Revision$ * @since 0.0.1 */ abstract class AbstractMoveTreeNodeProcessor { //HQL private final static String ISOLATE_NODE_HQL = "update %s t set t." + TreeAdapter.LEFT_PRO_NAME + "=0 - t." + TreeAdapter.LEFT_PRO_NAME + ",t." + TreeAdapter.RIGHT_PRO_NAME + "=0 - t." + TreeAdapter.RIGHT_PRO_NAME + " where (t." + TreeAdapter.LEFT_PRO_NAME + " between ? and ?)"; //?? private final static String UPDATE_NODES_AFFECTED = "update %1$s t set t." + TreeAdapter.LEFT_PRO_NAME + "=t." + TreeAdapter.LEFT_PRO_NAME + "+%2$d,t." + TreeAdapter.RIGHT_PRO_NAME + "=t." + TreeAdapter.RIGHT_PRO_NAME + "+%3$d where (t." + TreeAdapter.LEFT_PRO_NAME + " between ? and ?)"; //?NODE private final static String UPDATE_CURRENT_NODE_HQL = "update %1$s t set t." + TreeAdapter.LEFT_PRO_NAME + "=%2$d-t." + TreeAdapter.LEFT_PRO_NAME + " ,t." + TreeAdapter.RIGHT_PRO_NAME + "=%2$d-t." + TreeAdapter.RIGHT_PRO_NAME + " where t." + TreeAdapter.LEFT_PRO_NAME + " <?"; // private TreeAdapter parentNode; // ?? private TreeAdapter node; private EntityService entityService; // ?? private String treeClassName; private HibernateEntityService hibernateEntityService; /** * * * @return */ protected abstract TreeAdapter constructRootNode(); /** * ? * * @return ? */ public TreeAdapter getCurrentNode() { return this.node; } /** * ??? * * @return ?? */ protected String getTreeClassName() { return this.treeClassName; } protected Class getTreeClass() { try { return Class.forName(treeClassName); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } protected EntityService getEntityService() { return this.entityService; } // ??,? >= protected abstract int getMoveBlockLeftStart(); // ???,? <= protected abstract int getMoveBlockLeftEnd(); // ???? protected abstract int getOffset(); // ??? protected abstract int getUpdateWidth(); // ? protected abstract void appendQueryReplaceNodeCriteria(Criteria criteria); // ???? protected abstract void fetchMoveBlockInfo(List<? extends TreeAdapter> list); @SuppressWarnings("unchecked") public void execute(TreeAdapter node, EntityService service, HibernateEntityService hibernateEntityService, int n, Class<? extends TreeAdapter> clazz) { this.node = node; // this.ht = ht; this.entityService = service; this.hibernateEntityService = hibernateEntityService; if (clazz != null) { treeClassName = clazz.getName(); } else { treeClassName = entityService.getEntityClass(node).getName(); } // ?node service.refresh(node); // ? List list = fetchReplaceNode(Math.abs(n) - 1); // ???? fetchMoveBlockInfo(list); // ?? insulateCurrentNodeAndChildren(); // ?? updateNodesAffected(); // ? updateCurrentNode(); // ? service.refresh(node); if (list.size() > 0) { hibernateEntityService.evict(list.get(0)); } } /** * ?? * * @param n * ?? * @return ? */ private List<?> fetchReplaceNode(final int n) { return this.hibernateEntityService.executeFind(new HibernateCallback() { /** * @see org.springframework.orm.hibernate3.HibernateCallback#doInHibernate(org.hibernate.Session) */ @Override public Object doInHibernate(Session session) throws HibernateException, SQLException { Criteria criteria = session.createCriteria(entityService.getEntityClass(node)); appendQueryReplaceNodeCriteria(criteria); criteria.add(Restrictions.eq(TreeAdapter.DEPTH_PRO_NAME, node.getDepth())); criteria.setFirstResult(n); criteria.setMaxResults(1); return criteria.list(); } }); } // ??? private void insulateCurrentNodeAndChildren() { hibernateEntityService.bulkUpdate(String.format(ISOLATE_NODE_HQL, treeClassName), new Object[] { node.getLeft(), node.getRight() }); } // ?? private void updateNodesAffected() { String updateNodesAffectedHQL = String.format(UPDATE_NODES_AFFECTED, treeClassName, getUpdateWidth(), getUpdateWidth()); hibernateEntityService.bulkUpdate(updateNodesAffectedHQL, new Object[] { getMoveBlockLeftStart(), getMoveBlockLeftEnd() }); } // ?? private void updateCurrentNode() { String updateCurrentNodeHQL = String.format(UPDATE_CURRENT_NODE_HQL, treeClassName, getOffset()); hibernateEntityService.bulkUpdate(updateCurrentNodeHQL, new Object[] { 0 }); } /** * * * @return */ protected TreeAdapter getParentNode() { if (this.parentNode != null) { return this.parentNode; } if (node.getDepth() > 1) {// ?,? List<?> list = hibernateEntityService.executeFind(new HibernateCallback() { /** * @see org.springframework.orm.hibernate3.HibernateCallback#doInHibernate(org.hibernate.Session) */ @Override public Object doInHibernate(Session session) throws HibernateException, SQLException { Criteria criteria = session.createCriteria(treeClassName); /** * ? ??? ?? ? -1 */ criteria.add(Restrictions.gt(TreeAdapter.RIGHT_PRO_NAME, node.getRight())) .add(Restrictions.lt(TreeAdapter.LEFT_PRO_NAME, node.getLeft())); criteria.addOrder(Order.desc(TreeAdapter.LEFT_PRO_NAME)); criteria.setFirstResult(0); criteria.setMaxResults(1); return criteria.list(); } }); if (list.size() != 1) { // throw new RuntimeException("?(" + node.getLeft() + "," + node.getRight() + ")"); } parentNode = (TreeAdapter) list.get(0); } else { // ,? parentNode = constructRootNode(); } return parentNode; } }