corner.tree.services.impl.AbstractMoveTreeNodeProcessor.java Source code

Java tutorial

Introduction

Here is the source code for corner.tree.services.impl.AbstractMoveTreeNodeProcessor.java

Source

/* 
 * 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;
    }

}