001    /**
002     * Copyright (c) 2000-2013 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.concurrent.ThrowableAwareRunnable;
018    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.util.StringPool;
022    
023    import java.sql.Connection;
024    import java.sql.PreparedStatement;
025    import java.sql.ResultSet;
026    
027    import java.util.ArrayList;
028    import java.util.List;
029    
030    /**
031     * @author Shinn Lok
032     */
033    public class VerifyGroupId extends VerifyProcess {
034    
035            @Override
036            protected void doVerify() throws Exception {
037                    List<String> pendingModels = new ArrayList<String>();
038    
039                    for (String[] model : _MODELS) {
040                            pendingModels.add(model[0]);
041                    }
042    
043                    List<VerifiableGroupedModelRunnable> verifiableGroupedModelRunnables =
044                            new ArrayList<VerifiableGroupedModelRunnable>(_MODELS.length);
045    
046                    while (!pendingModels.isEmpty()) {
047                            int count = pendingModels.size();
048    
049                            for (String[] model : _MODELS) {
050                                    if (pendingModels.contains(model[2]) ||
051                                            !pendingModels.contains(model[0])) {
052    
053                                            continue;
054                                    }
055    
056                                    VerifiableGroupedModelRunnable verifyAuditedModelRunnable =
057                                            new VerifiableGroupedModelRunnable(
058                                                    model[0], model[1], model[2], model[3]);
059    
060                                    verifiableGroupedModelRunnables.add(verifyAuditedModelRunnable);
061    
062                                    verifyModel(model[0], model[1], model[2], model[3]);
063    
064                                    pendingModels.remove(model[0]);
065                            }
066    
067                            if (pendingModels.size() == count) {
068                                    throw new VerifyException(
069                                            "Circular dependency detected " + pendingModels);
070                            }
071                    }
072    
073                    doVerify(verifiableGroupedModelRunnables);
074            }
075    
076            protected long getGroupId(
077                            String modelName, String pkColumnName, long primKey)
078                    throws Exception {
079    
080                    Connection con = null;
081                    PreparedStatement ps = null;
082                    ResultSet rs = null;
083    
084                    try {
085                            con = DataAccess.getUpgradeOptimizedConnection();
086    
087                            ps = con.prepareStatement(
088                                    "select groupId from " + modelName + " where " + pkColumnName +
089                                            " = ?");
090    
091                            ps.setLong(1, primKey);
092    
093                            rs = ps.executeQuery();
094    
095                            if (rs.next()) {
096                                    return rs.getLong("groupId");
097                            }
098    
099                            if (_log.isDebugEnabled()) {
100                                    _log.debug(
101                                            "Unable to find " + modelName + StringPool.SPACE + primKey);
102                            }
103    
104                            return 0;
105                    }
106                    finally {
107                            DataAccess.cleanUp(con, ps, rs);
108                    }
109            }
110    
111            protected void verifyModel(
112                            String modelName, String pkColumnName, String relatedModelName,
113                            String relatedPKColumnName)
114                    throws Exception {
115    
116                    Connection con = null;
117                    PreparedStatement ps = null;
118                    ResultSet rs = null;
119    
120                    try {
121                            con = DataAccess.getUpgradeOptimizedConnection();
122    
123                            ps = con.prepareStatement(
124                                    "select " + pkColumnName + StringPool.COMMA_AND_SPACE +
125                                            relatedPKColumnName + " from " + modelName + " where " +
126                                                    "groupId is null");
127    
128                            rs = ps.executeQuery();
129    
130                            while (rs.next()) {
131                                    long primKey = rs.getLong(pkColumnName);
132                                    long relatedPrimKey = rs.getLong(relatedPKColumnName);
133    
134                                    long groupId = getGroupId(
135                                            relatedModelName, relatedPKColumnName, relatedPrimKey);
136    
137                                    if (groupId <= 0) {
138                                            continue;
139                                    }
140    
141                                    runSQL(
142                                            "update " + modelName + " set groupId = " + groupId +
143                                                    " where " + pkColumnName + " = " + primKey);
144                            }
145                    }
146                    finally {
147                            DataAccess.cleanUp(con, ps, rs);
148                    }
149            }
150    
151            private static final String[][] _MODELS = new String[][] {
152                    new String[] {
153                            "MBDiscussion", "discussionId", "MBThread", "threadId"
154                    },
155                    new String[] {
156                            "MBThreadFlag", "threadFlagId", "MBThread", "threadId"
157                    },
158                    new String[] {
159                            "PollsChoice", "choiceId", "PollsQuestion", "questionId"
160                    },
161                    new String[] {
162                            "PollsVote", "voteId", "PollsQuestion", "questionId"
163                    }
164            };
165    
166            private class VerifiableGroupedModelRunnable
167                    extends ThrowableAwareRunnable {
168    
169                    private VerifiableGroupedModelRunnable(
170                            String modelName, String pkColumnName, String relatedModelName,
171                            String relatedPKColumnName) {
172    
173                            _modelName = modelName;
174                            _pkColumnName = pkColumnName;
175                            _relatedModelName = relatedModelName;
176                            _relatedPKColumnName = relatedPKColumnName;
177                    }
178    
179                    @Override
180                    protected void doRun() throws Exception {
181                            verifyModel(
182                                    _modelName, _pkColumnName, _relatedModelName,
183                                    _relatedPKColumnName);
184                    }
185    
186                    private final String _modelName;
187                    private final String _pkColumnName;
188                    private final String _relatedModelName;
189                    private final String _relatedPKColumnName;
190    
191            }
192    
193            private static Log _log = LogFactoryUtil.getLog(VerifyGroupId.class);
194    
195    }