001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.persistence.impl;
016    
017    import com.liferay.portal.kernel.util.Validator;
018    import com.liferay.portal.model.NestedSetsTreeNodeModel;
019    
020    import java.util.List;
021    
022    /**
023     * @author Shuyang Zhou
024     */
025    public abstract class NestedSetsTreeManager<T extends NestedSetsTreeNodeModel> {
026    
027            public long countAncestors(T t) {
028                    return doCountAncestors(
029                            t.getNestedSetsTreeNodeScopeId(), t.getNestedSetsTreeNodeLeft(),
030                            t.getNestedSetsTreeNodeRight());
031            }
032    
033            public long countDescendants(T t) {
034                    return doCountDescendants(
035                            t.getNestedSetsTreeNodeScopeId(), t.getNestedSetsTreeNodeLeft(),
036                            t.getNestedSetsTreeNodeRight());
037            }
038    
039            public void delete(T t) {
040                    doUpdate(
041                            t.getNestedSetsTreeNodeScopeId(), -1, t.getNestedSetsTreeNodeLeft(),
042                            false, t.getNestedSetsTreeNodeRight(), false, null);
043                    doUpdate(
044                            t.getNestedSetsTreeNodeScopeId(), true, -2,
045                            t.getNestedSetsTreeNodeRight(), false);
046                    doUpdate(
047                            t.getNestedSetsTreeNodeScopeId(), false, -2,
048                            t.getNestedSetsTreeNodeRight(), false);
049            }
050    
051            public List<T> getAncestors(T t) {
052                    return doGetAncestors(
053                            t.getNestedSetsTreeNodeScopeId(), t.getNestedSetsTreeNodeLeft(),
054                            t.getNestedSetsTreeNodeRight());
055            }
056    
057            public List<T> getDescendants(T t) {
058                    return doGetDescendants(
059                            t.getNestedSetsTreeNodeScopeId(), t.getNestedSetsTreeNodeLeft(),
060                            t.getNestedSetsTreeNodeRight());
061            }
062    
063            public void insert(T t, T parentT) {
064                    if (parentT == null) {
065                            long maxNestedSetsTreeNodeRight = getMaxNestedSetsTreeNodeRight(
066                                    t.getNestedSetsTreeNodeScopeId());
067    
068                            t.setNestedSetsTreeNodeLeft(maxNestedSetsTreeNodeRight);
069                            t.setNestedSetsTreeNodeRight(maxNestedSetsTreeNodeRight + 1);
070                    }
071                    else {
072                            doUpdate(
073                                    t.getNestedSetsTreeNodeScopeId(), true, 2,
074                                    parentT.getNestedSetsTreeNodeRight(), true);
075                            doUpdate(
076                                    t.getNestedSetsTreeNodeScopeId(), false, 2,
077                                    parentT.getNestedSetsTreeNodeRight(), true);
078    
079                            t.setNestedSetsTreeNodeLeft(parentT.getNestedSetsTreeNodeRight());
080                            t.setNestedSetsTreeNodeRight(
081                                    parentT.getNestedSetsTreeNodeRight() + 1);
082                    }
083            }
084    
085            public void move(T t, T oldParentT, T newParentT) {
086                    if (Validator.equals(oldParentT, newParentT)) {
087                            return;
088                    }
089    
090                    List<T> descendants = doGetDescendants(
091                            t.getNestedSetsTreeNodeScopeId(), t.getNestedSetsTreeNodeLeft(),
092                            t.getNestedSetsTreeNodeRight());
093    
094                    long newParentNestedSetsTreeNodeRight = 0;
095    
096                    if (newParentT == null) {
097                            newParentNestedSetsTreeNodeRight = getMaxNestedSetsTreeNodeRight(
098                                    t.getNestedSetsTreeNodeScopeId());
099                    }
100                    else {
101                            newParentNestedSetsTreeNodeRight =
102                                    newParentT.getNestedSetsTreeNodeRight();
103                    }
104    
105                    long delta = 0;
106    
107                    if (t.getNestedSetsTreeNodeRight() < newParentNestedSetsTreeNodeRight) {
108                            doUpdate(
109                                    t.getNestedSetsTreeNodeScopeId(),
110                                    -(t.getNestedSetsTreeNodeRight() -
111                                            t.getNestedSetsTreeNodeLeft() + 1),
112                                    t.getNestedSetsTreeNodeRight(), false,
113                                    newParentNestedSetsTreeNodeRight, false, null);
114    
115                            delta =
116                                    newParentNestedSetsTreeNodeRight -
117                                            t.getNestedSetsTreeNodeRight() - 1;
118    
119                            doUpdate(
120                                    t.getNestedSetsTreeNodeScopeId(), delta,
121                                    t.getNestedSetsTreeNodeLeft(), true,
122                                    t.getNestedSetsTreeNodeRight(), true, descendants);
123                    }
124                    else {
125                            doUpdate(
126                                    t.getNestedSetsTreeNodeScopeId(),
127                                    t.getNestedSetsTreeNodeRight() -
128                                            t.getNestedSetsTreeNodeLeft() + 1,
129                                    newParentNestedSetsTreeNodeRight, true,
130                                    t.getNestedSetsTreeNodeLeft(), false, null);
131    
132                            delta =
133                                    newParentNestedSetsTreeNodeRight -
134                                            t.getNestedSetsTreeNodeLeft();
135    
136                            doUpdate(
137                                    t.getNestedSetsTreeNodeScopeId(), delta,
138                                    t.getNestedSetsTreeNodeLeft(), true,
139                                    t.getNestedSetsTreeNodeRight(), true, descendants);
140                    }
141    
142                    t.setNestedSetsTreeNodeLeft(t.getNestedSetsTreeNodeLeft() + delta);
143                    t.setNestedSetsTreeNodeRight(t.getNestedSetsTreeNodeRight() + delta);
144            }
145    
146            protected abstract long doCountAncestors(
147                    long nestedSetsTreeNodeScopeId, long nestedSetsTreeNodeLeft,
148                    long nestedSetsTreeNodeRight);
149    
150            protected abstract long doCountDescendants(
151                    long nestedSetsTreeNodeScopeId, long nestedSetsTreeNodeLeft,
152                    long nestedSetsTreeNodeRight);
153    
154            protected abstract List<T> doGetAncestors(
155                    long nestedSetsTreeNodeScopeId, long nestedSetsTreeNodeLeft,
156                    long nestedSetsTreeNodeRight);
157    
158            protected abstract List<T> doGetDescendants(
159                    long nestedSetsTreeNodeScopeId, long nestedSetsTreeNodeLeft,
160                    long nestedSetsTreeNodeRight);
161    
162            protected abstract void doUpdate(
163                    long nestedSetsTreeNodeScopeId, boolean leftOrRight, long delta,
164                    long limit, boolean inclusive);
165    
166            protected abstract void doUpdate(
167                    long nestedSetsTreeNodeScopeId, long delta, long start,
168                    boolean startInclusive, long end, boolean endInclusive,
169                    List<T> includeList);
170    
171            protected abstract long getMaxNestedSetsTreeNodeRight(
172                    long nestedSetsTreeNodeScopeId);
173    
174    }