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.upgrade.v5_2_0;
016    
017    import com.liferay.counter.service.CounterLocalServiceUtil;
018    import com.liferay.portal.NoSuchResourceException;
019    import com.liferay.portal.NoSuchRoleException;
020    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
021    import com.liferay.portal.kernel.dao.jdbc.SmartResultSet;
022    import com.liferay.portal.kernel.upgrade.UpgradeProcess;
023    import com.liferay.portal.kernel.util.ArrayUtil;
024    import com.liferay.portal.kernel.util.StringBundler;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.Validator;
027    import com.liferay.portal.model.ResourceCode;
028    import com.liferay.portal.model.ResourceConstants;
029    import com.liferay.portal.model.Role;
030    import com.liferay.portal.model.RoleConstants;
031    import com.liferay.portal.service.ResourceCodeLocalServiceUtil;
032    import com.liferay.portal.service.ResourceLocalServiceUtil;
033    import com.liferay.portal.service.RoleLocalServiceUtil;
034    import com.liferay.portal.util.PropsValues;
035    import com.liferay.portlet.asset.NoSuchTagException;
036    
037    import java.sql.Connection;
038    import java.sql.PreparedStatement;
039    import java.sql.ResultSet;
040    import java.sql.Timestamp;
041    
042    import java.util.HashMap;
043    import java.util.Map;
044    
045    /**
046     * @author Jorge Ferrer
047     * @author Brian Wing Shun Chan
048     */
049    public class UpgradeTags extends UpgradeProcess {
050    
051            protected void addEntry(
052                            long entryId, long groupId, long companyId, long userId,
053                            String userName, Timestamp createDate, Timestamp modifiedDate,
054                            long parentEntryId, String name, long vocabularyId)
055                    throws Exception {
056    
057                    Connection con = null;
058                    PreparedStatement ps = null;
059    
060                    try {
061                            con = DataAccess.getUpgradeOptimizedConnection();
062    
063                            ps = con.prepareStatement(
064                                    "insert into TagsEntry (entryId, groupId, companyId, userId, " +
065                                            "userName, createDate, modifiedDate, parentEntryId, " +
066                                                    "name, vocabularyId) values (?, ?, ?, ?, ?, ?, ?, ?, " +
067                                                            "?, ?)");
068    
069                            ps.setLong(1, entryId);
070                            ps.setLong(2, groupId);
071                            ps.setLong(3, companyId);
072                            ps.setLong(4, userId);
073                            ps.setString(5, userName);
074                            ps.setTimestamp(6, createDate);
075                            ps.setTimestamp(7, modifiedDate);
076                            ps.setLong(8, parentEntryId);
077                            ps.setString(9, name);
078                            ps.setLong(10, vocabularyId);
079    
080                            ps.executeUpdate();
081                    }
082                    finally {
083                            DataAccess.cleanUp(con, ps);
084                    }
085    
086                    addResources(
087                            companyId, "com.liferay.portlet.tags.model.TagsEntry",
088                            String.valueOf(entryId));
089            }
090    
091            protected void addProperty(
092                            long propertyId, long companyId, long userId, String userName,
093                            Timestamp createDate, Timestamp modifiedDate, long entryId,
094                            String key, String value)
095                    throws Exception {
096    
097                    Connection con = null;
098                    PreparedStatement ps = null;
099    
100                    try {
101                            con = DataAccess.getUpgradeOptimizedConnection();
102    
103                            ps = con.prepareStatement(
104                                    "insert into TagsProperty (propertyId, companyId, userId, " +
105                                            "userName, createDate, modifiedDate, entryId, key_, " +
106                                                    "value) values (?, ?, ?, ?, ?, ?, ?, ?, ?)");
107    
108                            ps.setLong(1, propertyId);
109                            ps.setLong(2, companyId);
110                            ps.setLong(3, userId);
111                            ps.setString(4, userName);
112                            ps.setTimestamp(5, createDate);
113                            ps.setTimestamp(6, modifiedDate);
114                            ps.setLong(7, entryId);
115                            ps.setString(8, key);
116                            ps.setString(9, value);
117    
118                            ps.executeUpdate();
119                    }
120                    finally {
121                            DataAccess.cleanUp(con, ps);
122                    }
123            }
124    
125            protected void addResource(long resourceCodeId, String primKey)
126                    throws Exception {
127    
128                    long resourceId = CounterLocalServiceUtil.increment(
129                            "com.liferay.portal.model.Resource");
130    
131                    StringBundler sb = new StringBundler(8);
132    
133                    sb.append("insert into Resource_ (resourceId, codeId, primKey) ");
134                    sb.append("values (");
135                    sb.append(resourceId);
136                    sb.append(", ");
137                    sb.append(resourceCodeId);
138                    sb.append(", '");
139                    sb.append(primKey);
140                    sb.append("')");
141    
142                    runSQL(sb.toString());
143            }
144    
145            protected void addResourceCode(
146                            long resourceCodeId, long companyId, String resourceName)
147                    throws Exception {
148    
149                    StringBundler sb = new StringBundler(10);
150    
151                    sb.append("insert into ResourceCode (codeId, companyId, name, scope) ");
152                    sb.append("values (");
153                    sb.append(resourceCodeId);
154                    sb.append(", ");
155                    sb.append(companyId);
156                    sb.append(", '");
157                    sb.append(resourceName);
158                    sb.append("', ");
159                    sb.append(ResourceConstants.SCOPE_INDIVIDUAL);
160                    sb.append(")");
161    
162                    runSQL(sb.toString());
163            }
164    
165            protected void addResourcePermission(
166                            long companyId, long roleId, String resourceName, String primKey)
167                    throws Exception {
168    
169                    StringBundler sb = new StringBundler(15);
170    
171                    sb.append("insert into ResourcePermission (resourcePermissionId, ");
172                    sb.append("companyId, name, scope, primKey, roleId, actionIds) ");
173                    sb.append("values (");
174                    sb.append(increment());
175                    sb.append(", ");
176                    sb.append(companyId);
177                    sb.append(", '");
178                    sb.append(resourceName);
179                    sb.append("', ");
180                    sb.append(ResourceConstants.SCOPE_INDIVIDUAL);
181                    sb.append(", '");
182                    sb.append(primKey);
183                    sb.append("', ");
184                    sb.append(roleId);
185                    sb.append(", 0)");
186    
187                    runSQL(sb.toString());
188            }
189    
190            protected void addResources(
191                            long companyId, String resourceName, String primKey)
192                    throws Exception {
193    
194                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
195                            ResourceCode resourceCode =
196                                    ResourceCodeLocalServiceUtil.getResourceCode(
197                                            companyId, resourceName,
198                                            ResourceConstants.SCOPE_INDIVIDUAL);
199    
200                            try {
201                                    ResourceLocalServiceUtil.getResource(
202                                            companyId, resourceName, ResourceConstants.SCOPE_INDIVIDUAL,
203                                            primKey);
204                            }
205                            catch (NoSuchResourceException nsre) {
206                                    addResource(resourceCode.getCodeId(), primKey);
207                            }
208                    }
209                    else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
210                            try {
211                                    Role role = RoleLocalServiceUtil.getRole(
212                                            companyId, RoleConstants.OWNER);
213    
214                                    addResourcePermission(
215                                            companyId, role.getRoleId(), resourceName, primKey);
216                            }
217                            catch (NoSuchRoleException nsre) {
218                            }
219                    }
220            }
221    
222            protected long addVocabulary(
223                            long vocabularyId, long groupId, long companyId, long userId,
224                            String userName, String name)
225                    throws Exception {
226    
227                    Timestamp now = new Timestamp(System.currentTimeMillis());
228    
229                    Connection con = null;
230                    PreparedStatement ps = null;
231                    ResultSet rs = null;
232    
233                    try {
234                            con = DataAccess.getUpgradeOptimizedConnection();
235    
236                            StringBuilder sb = new StringBuilder();
237    
238                            sb.append("insert into TagsVocabulary (vocabularyId, groupId, ");
239                            sb.append("companyId, userId, userName, createDate, ");
240                            sb.append("modifiedDate, name, description, folksonomy) values (");
241                            sb.append("?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
242    
243                            String sql = sb.toString();
244    
245                            ps = con.prepareStatement(sql);
246    
247                            ps.setLong(1, vocabularyId);
248                            ps.setLong(2, groupId);
249                            ps.setLong(3, companyId);
250                            ps.setLong(4, userId);
251                            ps.setString(5, userName);
252                            ps.setTimestamp(6, now);
253                            ps.setTimestamp(7, now);
254                            ps.setString(8, name);
255                            ps.setString(9, StringPool.BLANK);
256                            ps.setBoolean(10, true);
257    
258                            ps.executeUpdate();
259    
260                    }
261                    finally {
262                            DataAccess.cleanUp(con, ps, rs);
263                    }
264    
265                    addResources(
266                            companyId, "com.liferay.portlet.tags.model.TagsVocabulary",
267                            String.valueOf(vocabularyId));
268    
269                    return vocabularyId;
270            }
271    
272            protected long copyEntry(long groupId, long entryId) throws Exception {
273                    String key = groupId + StringPool.UNDERLINE + entryId;
274    
275                    Long newEntryId = _entryIdsMap.get(key);
276    
277                    if (newEntryId != null) {
278                            return newEntryId.longValue();
279                    }
280    
281                    Connection con = null;
282                    PreparedStatement ps = null;
283                    ResultSet rs = null;
284    
285                    try {
286                            con = DataAccess.getUpgradeOptimizedConnection();
287    
288                            ps = con.prepareStatement(
289                                    "select * from TagsEntry where entryId = ?",
290                                    ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
291    
292                            ps.setLong(1, entryId);
293    
294                            rs = ps.executeQuery();
295    
296                            while (rs.next()) {
297                                    long companyId = rs.getLong("companyId");
298                                    long userId = rs.getLong("userId");
299                                    String userName = rs.getString("userName");
300                                    Timestamp createDate = rs.getTimestamp("createDate");
301                                    Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
302                                    long parentEntryId = rs.getLong("parentEntryId");
303                                    String name = rs.getString("name");
304                                    long vocabularyId = rs.getLong("vocabularyId");
305    
306                                    newEntryId = increment();
307    
308                                    addEntry(
309                                            newEntryId, groupId, companyId, userId, userName,
310                                            createDate, modifiedDate, parentEntryId, name,
311                                            vocabularyId);
312    
313                                    copyProperties(entryId, newEntryId);
314    
315                                    _entryIdsMap.put(key, newEntryId);
316    
317                                    return newEntryId;
318                            }
319                    }
320                    finally {
321                            DataAccess.cleanUp(con, ps, rs);
322                    }
323    
324                    throw new NoSuchTagException(
325                            "No AssetTag exists with the primary key " + entryId);
326            }
327    
328            protected void copyProperties(long entryId, long newEntryId)
329                    throws Exception {
330    
331                    Connection con = null;
332                    PreparedStatement ps = null;
333                    ResultSet rs = null;
334    
335                    try {
336                            con = DataAccess.getUpgradeOptimizedConnection();
337    
338                            ps = con.prepareStatement(
339                                    "select * from TagsProperty where entryId = ?",
340                                    ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
341    
342                            ps.setLong(1, entryId);
343    
344                            rs = ps.executeQuery();
345    
346                            while (rs.next()) {
347                                    long companyId = rs.getLong("companyId");
348                                    long userId = rs.getLong("userId");
349                                    String userName = rs.getString("userName");
350                                    Timestamp createDate = rs.getTimestamp("createDate");
351                                    Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
352                                    String key = rs.getString("key_");
353                                    String value = rs.getString("value");
354    
355                                    long newPropertyId = increment();
356    
357                                    addProperty(
358                                            newPropertyId, companyId, userId, userName, createDate,
359                                            modifiedDate, newEntryId, key, value);
360                            }
361                    }
362                    finally {
363                            DataAccess.cleanUp(con, ps, rs);
364                    }
365            }
366    
367            protected void deleteEntries() throws Exception {
368                    Connection con = null;
369                    PreparedStatement ps = null;
370                    ResultSet rs = null;
371    
372                    try {
373                            con = DataAccess.getUpgradeOptimizedConnection();
374    
375                            ps = con.prepareStatement(
376                                    "select entryId from TagsEntry where groupId = 0");
377    
378                            rs = ps.executeQuery();
379    
380                            while (rs.next()) {
381                                    long entryId = rs.getLong("entryId");
382    
383                                    runSQL(
384                                            "delete from TagsAssets_TagsEntries where entryId = " +
385                                                    entryId);
386    
387                                    runSQL("delete from TagsProperty where entryId = " + entryId);
388                            }
389    
390                            runSQL("delete from TagsEntry where groupId = 0");
391                    }
392                    finally {
393                            DataAccess.cleanUp(con, ps, rs);
394                    }
395            }
396    
397            @Override
398            protected void doUpgrade() throws Exception {
399                    updateGroupIds();
400                    updateCategories();
401                    updateAssets();
402            }
403    
404            protected long getVocabularyId(
405                            long groupId, long companyId, long userId, String userName,
406                            String name)
407                    throws Exception {
408    
409                    name = name.trim();
410    
411                    if (Validator.isNull(name) ||
412                            ArrayUtil.contains(_DEFAULT_CATEGORY_PROPERTY_VALUES, name)) {
413    
414                            name = _DEFAULT_TAGS_VOCABULARY;
415                    }
416    
417                    String key = groupId + StringPool.UNDERLINE + name;
418    
419                    Long vocabularyId = _vocabularyIdsMap.get(key);
420    
421                    if (vocabularyId != null) {
422                            return vocabularyId.longValue();
423                    }
424    
425                    Connection con = null;
426                    PreparedStatement ps = null;
427                    ResultSet rs = null;
428    
429                    try {
430                            con = DataAccess.getUpgradeOptimizedConnection();
431    
432                            ps = con.prepareStatement(
433                                    "select vocabularyId from TagsVocabulary where groupId = ? " +
434                                            "and name = ?");
435    
436                            ps.setLong(1, groupId);
437                            ps.setString(2, name);
438    
439                            rs = ps.executeQuery();
440    
441                            if (rs.next()) {
442                                    vocabularyId = rs.getLong("vocabularyId");
443                            }
444                            else {
445                                    long newVocabularyId = increment();
446    
447                                    vocabularyId = addVocabulary(
448                                            newVocabularyId, groupId, companyId, userId, userName,
449                                            name);
450                            }
451                    }
452                    finally {
453                            DataAccess.cleanUp(con, ps, rs);
454                    }
455    
456                    _vocabularyIdsMap.put(key, vocabularyId);
457    
458                    return vocabularyId.longValue();
459            }
460    
461            protected void updateAssets() throws Exception {
462                    Connection con = null;
463                    PreparedStatement ps = null;
464                    ResultSet rs = null;
465    
466                    try {
467                            con = DataAccess.getUpgradeOptimizedConnection();
468    
469                            ps = con.prepareStatement(
470                                    "select resourcePrimKey from JournalArticle where approved " +
471                                            "= ?");
472    
473                            ps.setBoolean(1, false);
474    
475                            rs = ps.executeQuery();
476    
477                            while (rs.next()) {
478                                    long resourcePrimKey = rs.getLong("resourcePrimKey");
479    
480                                    runSQL(
481                                            "update TagsAsset set visible = FALSE where classPK = " +
482                                                    resourcePrimKey);
483                            }
484                    }
485                    finally {
486                            DataAccess.cleanUp(con, ps, rs);
487                    }
488            }
489    
490            protected void updateCategories() throws Exception {
491                    Connection con = null;
492                    PreparedStatement ps = null;
493                    ResultSet rs = null;
494    
495                    try {
496                            con = DataAccess.getUpgradeOptimizedConnection();
497    
498                            StringBuilder sb = new StringBuilder();
499    
500                            sb.append("select TE.entryId, TE.groupId, TE.companyId, ");
501                            sb.append("TE.userId, TE.userName, TP.propertyId, TP.value from ");
502                            sb.append("TagsEntry TE, TagsProperty TP where TE.entryId = ");
503                            sb.append("TP.entryId and TE.vocabularyId <= 0 and TP.key_ = ");
504                            sb.append("'category'");
505    
506                            String sql = sb.toString();
507    
508                            ps = con.prepareStatement(sql);
509    
510                            rs = ps.executeQuery();
511    
512                            SmartResultSet srs = new SmartResultSet(rs);
513    
514                            while (srs.next()) {
515                                    long entryId = srs.getLong("TE.entryId");
516                                    long groupId = srs.getLong("TE.groupId");
517                                    long companyId = srs.getLong("TE.companyId");
518                                    long userId = srs.getLong("TE.userId");
519                                    String userName = srs.getString("TE.userName");
520                                    long propertyId = srs.getLong("TP.propertyId");
521                                    String value = srs.getString("TP.value");
522    
523                                    long vocabularyId = getVocabularyId(
524                                            groupId, companyId, userId, userName, value);
525    
526                                    runSQL(
527                                            "update TagsEntry set vocabularyId = " + vocabularyId +
528                                                    " where entryId = " + entryId);
529    
530                                    runSQL(
531                                            "delete from TagsProperty where propertyId = " +
532                                                    propertyId);
533                            }
534                    }
535                    finally {
536                            DataAccess.cleanUp(con, ps, rs);
537                    }
538            }
539    
540            protected void updateGroupIds() throws Exception {
541                    Connection con = null;
542                    PreparedStatement ps = null;
543                    ResultSet rs = null;
544    
545                    try {
546                            con = DataAccess.getUpgradeOptimizedConnection();
547    
548                            ps = con.prepareStatement(
549                                    "select TA.assetId, TA.groupId, TA_TE.entryId from " +
550                                            "TagsAssets_TagsEntries TA_TE inner join TagsAsset TA on " +
551                                                    "TA.assetId = TA_TE.assetId",
552                                    ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
553    
554                            rs = ps.executeQuery();
555    
556                            SmartResultSet srs = new SmartResultSet(rs);
557    
558                            while (srs.next()) {
559                                    long assetId = srs.getLong("TA.assetId");
560                                    long groupId = srs.getLong("TA.groupId");
561                                    long entryId = srs.getLong("TA_TE.entryId");
562    
563                                    long newEntryId = copyEntry(groupId, entryId);
564    
565                                    runSQL(
566                                            "insert into TagsAssets_TagsEntries (assetId, entryId) " +
567                                                    "values (" + assetId + ", " + newEntryId + ")");
568                            }
569                    }
570                    finally {
571                            DataAccess.cleanUp(con, ps, rs);
572                    }
573    
574                    deleteEntries();
575            }
576    
577            private static final String[] _DEFAULT_CATEGORY_PROPERTY_VALUES = {
578                    "undefined", "no category", "category"
579            };
580    
581            private static final String _DEFAULT_TAGS_VOCABULARY = "Default Tag Set";
582    
583            private Map<String, Long> _entryIdsMap = new HashMap<String, Long>();
584            private Map<String, Long> _vocabularyIdsMap = new HashMap<String, Long>();
585    
586    }