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.verify;
016    
017    import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
018    import com.liferay.portal.kernel.concurrent.ThrowableAwareRunnable;
019    import com.liferay.portal.kernel.dao.jdbc.AutoBatchPreparedStatementUtil;
020    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.util.LoggingTimer;
024    import com.liferay.portal.kernel.util.StringBundler;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.verify.model.VerifiableGroupedModel;
027    
028    import java.sql.Connection;
029    import java.sql.PreparedStatement;
030    import java.sql.ResultSet;
031    
032    import java.util.ArrayList;
033    import java.util.Collection;
034    import java.util.List;
035    import java.util.Map;
036    
037    /**
038     * @author Shinn Lok
039     */
040    public class VerifyGroupedModel extends VerifyProcess {
041    
042            public void verify(VerifiableGroupedModel... verifiableGroupedModels)
043                    throws Exception {
044    
045                    List<String> unverifiedTableNames = new ArrayList<>();
046    
047                    for (VerifiableGroupedModel verifiableGroupedModel :
048                                    verifiableGroupedModels) {
049    
050                            unverifiedTableNames.add(verifiableGroupedModel.getTableName());
051                    }
052    
053                    List<VerifiableGroupedModelRunnable> verifiableGroupedModelRunnables =
054                            new ArrayList<>(unverifiedTableNames.size());
055    
056                    while (!unverifiedTableNames.isEmpty()) {
057                            int count = unverifiedTableNames.size();
058    
059                            for (VerifiableGroupedModel verifiableGroupedModel :
060                                            verifiableGroupedModels) {
061    
062                                    if (unverifiedTableNames.contains(
063                                                    verifiableGroupedModel.getRelatedTableName()) ||
064                                            !unverifiedTableNames.contains(
065                                                    verifiableGroupedModel.getTableName())) {
066    
067                                            continue;
068                                    }
069    
070                                    VerifiableGroupedModelRunnable verifyAuditedModelRunnable =
071                                            new VerifiableGroupedModelRunnable(verifiableGroupedModel);
072    
073                                    verifiableGroupedModelRunnables.add(verifyAuditedModelRunnable);
074    
075                                    unverifiedTableNames.remove(
076                                            verifiableGroupedModel.getTableName());
077                            }
078    
079                            if (unverifiedTableNames.size() == count) {
080                                    throw new VerifyException(
081                                            "Circular dependency detected " + unverifiedTableNames);
082                            }
083                    }
084    
085                    doVerify(verifiableGroupedModelRunnables);
086            }
087    
088            @Override
089            protected void doVerify() throws Exception {
090                    Map<String, VerifiableGroupedModel> verifiableGroupedModelsMap =
091                            PortalBeanLocatorUtil.locate(VerifiableGroupedModel.class);
092    
093                    Collection<VerifiableGroupedModel> verifiableGroupedModels =
094                            verifiableGroupedModelsMap.values();
095    
096                    verify(
097                            verifiableGroupedModels.toArray(
098                                    new VerifiableGroupedModel[verifiableGroupedModels.size()]));
099            }
100    
101            protected long getGroupId(
102                            Connection con, String tableName, String primaryKeColumnName,
103                            long primKey)
104                    throws Exception {
105    
106                    try (PreparedStatement ps = con.prepareStatement(
107                                    "select groupId from " + tableName + " where " +
108                                            primaryKeColumnName + " = ?")) {
109    
110                            ps.setLong(1, primKey);
111    
112                            try (ResultSet rs = ps.executeQuery()) {
113                                    if (rs.next()) {
114                                            return rs.getLong("groupId");
115                                    }
116    
117                                    if (_log.isDebugEnabled()) {
118                                            _log.debug("Unable to find " + tableName + " " + primKey);
119                                    }
120    
121                                    return 0;
122                            }
123                    }
124            }
125    
126            @Override
127            protected boolean isForceConcurrent(
128                    Collection<? extends ThrowableAwareRunnable> throwableAwareRunnables) {
129    
130                    return true;
131            }
132    
133            protected void verifyGroupedModel(
134                            VerifiableGroupedModel verifiableGroupedModel)
135                    throws Exception {
136    
137                    try (LoggingTimer loggingTimer = new LoggingTimer(
138                                    verifiableGroupedModel.getTableName())) {
139    
140                            StringBundler sb = new StringBundler(7);
141    
142                            sb.append("select ");
143                            sb.append(verifiableGroupedModel.getPrimaryKeyColumnName());
144                            sb.append(StringPool.COMMA_AND_SPACE);
145                            sb.append(verifiableGroupedModel.getRelatedPrimaryKeyColumnName());
146                            sb.append(" from ");
147                            sb.append(verifiableGroupedModel.getTableName());
148                            sb.append(" where groupId is null");
149    
150                            try (Connection con = DataAccess.getUpgradeOptimizedConnection();
151                                    PreparedStatement ps1 = con.prepareStatement(sb.toString());
152                                    ResultSet rs = ps1.executeQuery()) {
153    
154                                    sb = new StringBundler(5);
155    
156                                    sb.append("update ");
157                                    sb.append(verifiableGroupedModel.getTableName());
158                                    sb.append(" set groupId = ? where ");
159                                    sb.append(verifiableGroupedModel.getPrimaryKeyColumnName());
160                                    sb.append(" = ?");
161    
162                                    try (PreparedStatement ps2 =
163                                                    AutoBatchPreparedStatementUtil.autoBatch(
164                                                            con.prepareStatement(sb.toString()))) {
165    
166                                            while (rs.next()) {
167                                                    long primKey = rs.getLong(
168                                                            verifiableGroupedModel.getPrimaryKeyColumnName());
169                                                    long relatedPrimKey = rs.getLong(
170                                                            verifiableGroupedModel.
171                                                                    getRelatedPrimaryKeyColumnName());
172    
173                                                    long groupId = getGroupId(
174                                                            con, verifiableGroupedModel.getRelatedTableName(),
175                                                            verifiableGroupedModel.
176                                                                    getRelatedPrimaryKeyColumnName(),
177                                                            relatedPrimKey);
178    
179                                                    if (groupId <= 0) {
180                                                            continue;
181                                                    }
182    
183                                                    ps2.setLong(1, groupId);
184                                                    ps2.setLong(2, primKey);
185    
186                                                    ps2.addBatch();
187                                            }
188    
189                                            ps2.executeBatch();
190                                    }
191                            }
192                    }
193            }
194    
195            private static final Log _log = LogFactoryUtil.getLog(
196                    VerifyGroupedModel.class);
197    
198            private class VerifiableGroupedModelRunnable
199                    extends ThrowableAwareRunnable {
200    
201                    public VerifiableGroupedModelRunnable(
202                            VerifiableGroupedModel verifiableGroupedModel) {
203    
204                            _verifiableGroupedModel = verifiableGroupedModel;
205                    }
206    
207                    @Override
208                    protected void doRun() throws Exception {
209                            verifyGroupedModel(_verifiableGroupedModel);
210                    }
211    
212                    private final VerifiableGroupedModel _verifiableGroupedModel;
213    
214            }
215    
216    }