001
014
015 package com.liferay.portal.kernel.tree;
016
017 import com.liferay.portal.kernel.exception.PortalException;
018 import com.liferay.portal.kernel.model.TreeModel;
019 import com.liferay.portal.kernel.util.GetterUtil;
020 import com.liferay.portal.kernel.util.PropsKeys;
021 import com.liferay.portal.kernel.util.PropsUtil;
022 import com.liferay.portal.kernel.util.ReflectionUtil;
023 import com.liferay.portal.kernel.util.StringPool;
024 import com.liferay.portal.kernel.util.VerifyThreadLocal;
025
026 import java.util.Deque;
027 import java.util.LinkedList;
028 import java.util.List;
029 import java.util.concurrent.ForkJoinPool;
030 import java.util.concurrent.RecursiveAction;
031
032
035 public class TreePathUtil {
036
037 public static void rebuildTree(
038 long companyId, long parentPrimaryKey, String parentTreePath,
039 TreeModelTasks<?> treeModelTasks)
040 throws PortalException {
041
042 if (VerifyThreadLocal.isVerifyInProgress() &&
043 _VERIFY_DATABASE_TRANSACTIONS_DISABLED) {
044
045 ForkJoinPool forkJoinPool = new ForkJoinPool();
046
047 try {
048 forkJoinPool.invoke(
049 new RecursiveRebuildTreeTask(
050 treeModelTasks, companyId, parentPrimaryKey,
051 parentTreePath, 0L));
052 }
053 finally {
054 forkJoinPool.shutdown();
055 }
056
057 return;
058 }
059
060 Deque<Object[]> traces = new LinkedList<>();
061
062 traces.push(new Object[] {parentPrimaryKey, parentTreePath, 0L});
063
064 Object[] trace = null;
065
066 while ((trace = traces.poll()) != null) {
067 Long curParentPrimaryKey = (Long)trace[0];
068 String curParentTreePath = (String)trace[1];
069 Long previousPrimaryKey = (Long)trace[2];
070
071 treeModelTasks.rebuildDependentModelsTreePaths(
072 curParentPrimaryKey, curParentTreePath);
073
074 List<? extends TreeModel> treeModels =
075 treeModelTasks.findTreeModels(
076 previousPrimaryKey, companyId, curParentPrimaryKey,
077 _MODEL_TREE_REBUILD_QUERY_RESULTS_BATCH_SIZE);
078
079 if (treeModels.isEmpty()) {
080 continue;
081 }
082
083 if (treeModels.size() ==
084 _MODEL_TREE_REBUILD_QUERY_RESULTS_BATCH_SIZE) {
085
086 TreeModel treeModel = treeModels.get(treeModels.size() - 1);
087
088 trace[2] = treeModel.getPrimaryKeyObj();
089
090 traces.push(trace);
091 }
092
093 for (TreeModel treeModel : treeModels) {
094 String treePath = curParentTreePath.concat(
095 String.valueOf(treeModel.getPrimaryKeyObj())).concat(
096 StringPool.SLASH);
097
098 if (!treePath.equals(treeModel.getTreePath())) {
099 treeModel.updateTreePath(treePath);
100 }
101
102 traces.push(
103 new Object[] {treeModel.getPrimaryKeyObj(), treePath, 0L});
104 }
105 }
106 }
107
108 private static final int _MODEL_TREE_REBUILD_QUERY_RESULTS_BATCH_SIZE =
109 GetterUtil.getInteger(
110 PropsUtil.get(
111 PropsKeys.MODEL_TREE_REBUILD_QUERY_RESULTS_BATCH_SIZE));
112
113 private static final boolean _VERIFY_DATABASE_TRANSACTIONS_DISABLED =
114 GetterUtil.getBoolean(
115 PropsUtil.get(PropsKeys.VERIFY_DATABASE_TRANSACTIONS_DISABLED));
116
117 private static class RecursiveRebuildTreeTask extends RecursiveAction {
118
119 @Override
120 protected void compute() {
121 try {
122 _treeModelTasks.rebuildDependentModelsTreePaths(
123 _parentPrimaryKey, _parentTreePath);
124 }
125 catch (PortalException pe) {
126 ReflectionUtil.throwException(pe);
127 }
128
129 List<? extends TreeModel> treeModels =
130 _treeModelTasks.findTreeModels(
131 _previousPrimaryKey, _companyId, _parentPrimaryKey,
132 _MODEL_TREE_REBUILD_QUERY_RESULTS_BATCH_SIZE);
133
134 if (treeModels.isEmpty()) {
135 return;
136 }
137
138 if (treeModels.size() ==
139 _MODEL_TREE_REBUILD_QUERY_RESULTS_BATCH_SIZE) {
140
141 TreeModel treeModel = treeModels.get(treeModels.size() - 1);
142
143 RecursiveRebuildTreeTask recursiveRebuildTreeTask =
144 new RecursiveRebuildTreeTask(
145 _treeModelTasks, _companyId, _parentPrimaryKey,
146 _parentTreePath, (long)treeModel.getPrimaryKeyObj());
147
148 recursiveRebuildTreeTask.fork();
149 }
150
151 for (TreeModel treeModel : treeModels) {
152 String treePath = _parentTreePath.concat(
153 String.valueOf(treeModel.getPrimaryKeyObj())).concat(
154 StringPool.SLASH);
155
156 if (!treePath.equals(treeModel.getTreePath())) {
157 treeModel.updateTreePath(treePath);
158 }
159
160 RecursiveRebuildTreeTask recursiveRebuildTreeTask =
161 new RecursiveRebuildTreeTask(
162 _treeModelTasks, _companyId,
163 (long)treeModel.getPrimaryKeyObj(), treePath, 0L);
164
165 recursiveRebuildTreeTask.fork();
166 }
167 }
168
169 private RecursiveRebuildTreeTask(
170 TreeModelTasks<?> treeModelTasks, long companyId,
171 long parentPrimaryKey, String parentTreePath,
172 long previousPrimaryKey) {
173
174 _treeModelTasks = treeModelTasks;
175 _companyId = companyId;
176 _parentPrimaryKey = parentPrimaryKey;
177 _parentTreePath = parentTreePath;
178 _previousPrimaryKey = previousPrimaryKey;
179 }
180
181 private final long _companyId;
182 private final long _parentPrimaryKey;
183 private final String _parentTreePath;
184 private final long _previousPrimaryKey;
185 private final TreeModelTasks<?> _treeModelTasks;
186
187 }
188
189 }