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.kernel.dao.db;
016    
017    import aQute.bnd.annotation.ProviderType;
018    
019    import com.liferay.portal.kernel.util.HashUtil;
020    import com.liferay.portal.kernel.util.StringBundler;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.StringUtil;
023    import com.liferay.portal.kernel.util.Validator;
024    
025    import java.util.Arrays;
026    
027    /**
028     * @author James Lefeu
029     * @author Peter Shin
030     * @author Shuyang Zhou
031     */
032    @ProviderType
033    public class IndexMetadata extends Index implements Comparable<IndexMetadata> {
034    
035            public IndexMetadata(
036                    String indexName, String tableName, boolean unique,
037                    String... columnNames) {
038    
039                    super(indexName, tableName, unique);
040    
041                    if (columnNames == null) {
042                            throw new NullPointerException("Column names are missing");
043                    }
044    
045                    _columnNames = columnNames;
046    
047                    StringBundler sb = new StringBundler(5);
048    
049                    sb.append("drop index ");
050                    sb.append(indexName);
051                    sb.append(" on ");
052                    sb.append(tableName);
053                    sb.append(StringPool.SEMICOLON);
054    
055                    _dropSQL = sb.toString();
056            }
057    
058            @Override
059            public int compareTo(IndexMetadata indexMetadata) {
060                    String columnNames = StringUtil.merge(getColumnNames());
061    
062                    String indexMetadataColumnNames = StringUtil.merge(
063                            indexMetadata.getColumnNames());
064    
065                    return columnNames.compareTo(indexMetadataColumnNames);
066            }
067    
068            @Override
069            public boolean equals(Object obj) {
070                    if (this == obj) {
071                            return true;
072                    }
073    
074                    if (!(obj instanceof IndexMetadata)) {
075                            return false;
076                    }
077    
078                    IndexMetadata indexMetadata = (IndexMetadata)obj;
079    
080                    if (Validator.equals(getTableName(), indexMetadata.getTableName()) &&
081                            Arrays.equals(_columnNames, indexMetadata._columnNames)) {
082    
083                            return true;
084                    }
085    
086                    return false;
087            }
088    
089            public String[] getColumnNames() {
090                    String[] columnNames = _columnNames.clone();
091    
092                    for (int i = 0; i < columnNames.length; i++) {
093                            int index = columnNames[i].indexOf("[$COLUMN_LENGTH:");
094    
095                            if (index > 0) {
096                                    columnNames[i] = columnNames[i].substring(0, index);
097                            }
098                    }
099    
100                    return columnNames;
101            }
102    
103            public String getCreateSQL(int[] lengths) {
104                    int sbSize = 8 + _columnNames.length * 2;
105    
106                    if (lengths != null) {
107                            sbSize += _columnNames.length * 3;
108                    }
109    
110                    StringBundler sb = new StringBundler(sbSize);
111    
112                    if (isUnique()) {
113                            sb.append("create unique ");
114                    }
115                    else {
116                            sb.append("create ");
117                    }
118    
119                    sb.append("index ");
120                    sb.append(getIndexName());
121                    sb.append(" on ");
122                    sb.append(getTableName());
123    
124                    sb.append(StringPool.SPACE);
125                    sb.append(StringPool.OPEN_PARENTHESIS);
126    
127                    for (int i = 0; i < _columnNames.length; i++) {
128                            sb.append(_columnNames[i]);
129    
130                            if ((lengths != null) && (lengths[i] > 0)) {
131                                    sb.append("[$COLUMN_LENGTH:");
132                                    sb.append(lengths[i]);
133                                    sb.append("$]");
134                            }
135    
136                            sb.append(StringPool.COMMA_AND_SPACE);
137                    }
138    
139                    sb.setIndex(sb.index() - 1);
140    
141                    sb.append(StringPool.CLOSE_PARENTHESIS);
142                    sb.append(StringPool.SEMICOLON);
143    
144                    return sb.toString();
145            }
146    
147            public String getDropSQL() {
148                    return _dropSQL;
149            }
150    
151            @Override
152            public int hashCode() {
153                    int hashCode = HashUtil.hash(0, getTableName());
154    
155                    for (String columnName : _columnNames) {
156                            hashCode = HashUtil.hash(hashCode, columnName);
157                    }
158    
159                    return hashCode;
160            }
161    
162            public Boolean redundantTo(IndexMetadata indexMetadata) {
163                    String[] indexMetadataColumnNames = indexMetadata._columnNames;
164    
165                    if (_columnNames.length <= indexMetadataColumnNames.length) {
166                            for (int i = 0; i < _columnNames.length; i++) {
167                                    if (!_columnNames[i].equals(indexMetadataColumnNames[i])) {
168                                            return null;
169                                    }
170                            }
171    
172                            if (isUnique()) {
173                                    return Boolean.FALSE;
174                            }
175                            else {
176                                    return Boolean.TRUE;
177                            }
178                    }
179    
180                    Boolean redundant = indexMetadata.redundantTo(this);
181    
182                    if (redundant == null) {
183                            return null;
184                    }
185    
186                    return !redundant;
187            }
188    
189            @Override
190            public String toString() {
191                    return getCreateSQL(null);
192            }
193    
194            private final String[] _columnNames;
195            private final String _dropSQL;
196    
197    }