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.upgrade.v6_2_0;
016    
017    import com.liferay.document.library.kernel.model.DLFileEntry;
018    import com.liferay.document.library.kernel.model.DLFileEntryMetadata;
019    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.metadata.RawMetadataProcessor;
023    import com.liferay.portal.kernel.upgrade.UpgradeProcess;
024    import com.liferay.portal.kernel.util.ArrayUtil;
025    import com.liferay.portal.kernel.util.PortalUtil;
026    import com.liferay.portal.kernel.util.StringPool;
027    import com.liferay.portal.kernel.util.StringUtil;
028    import com.liferay.portal.kernel.util.Validator;
029    import com.liferay.portal.kernel.xml.Document;
030    import com.liferay.portal.kernel.xml.Element;
031    import com.liferay.portal.kernel.xml.SAXReaderUtil;
032    import com.liferay.portal.upgrade.v6_2_0.util.DDMTemplateTable;
033    import com.liferay.util.xml.XMLUtil;
034    
035    import java.sql.Connection;
036    import java.sql.PreparedStatement;
037    import java.sql.ResultSet;
038    import java.sql.SQLException;
039    
040    import java.util.List;
041    
042    /**
043     * @author Juan Fernández
044     * @author Marcellus Tavares
045     */
046    public class UpgradeDynamicDataMapping extends UpgradeProcess {
047    
048            @Override
049            protected void doUpgrade() throws Exception {
050                    updateSchema();
051    
052                    updateStructures();
053                    updateStructuresClassNameId();
054    
055                    updateTemplates();
056            }
057    
058            protected void updateMetadataElement(
059                    Element metadataElement, String[] relocatedMetadadaEntryNames,
060                    String[] removedMetadataEntryNames) {
061    
062                    Element parentElement = metadataElement.getParent();
063    
064                    List<Element> entryElements = metadataElement.elements("entry");
065    
066                    for (Element entryElement : entryElements) {
067                            String name = entryElement.attributeValue("name");
068    
069                            if (ArrayUtil.contains(removedMetadataEntryNames, name)) {
070                                    metadataElement.remove(entryElement);
071                            }
072                            else if (ArrayUtil.contains(relocatedMetadadaEntryNames, name)) {
073                                    parentElement.addAttribute(name, entryElement.getText());
074    
075                                    metadataElement.remove(entryElement);
076                            }
077                    }
078            }
079    
080            protected void updateSchema() throws Exception {
081                    try {
082                            runSQL("alter table DDMTemplate add classNameId LONG");
083    
084                            runSQL("alter table DDMTemplate add templateKey STRING");
085    
086                            runSQL("alter_column_name DDMTemplate structureId classPK LONG");
087                    }
088                    catch (SQLException sqle) {
089                            upgradeTable(
090                                    DDMTemplateTable.TABLE_NAME, DDMTemplateTable.TABLE_COLUMNS,
091                                    DDMTemplateTable.TABLE_SQL_CREATE,
092                                    DDMTemplateTable.TABLE_SQL_ADD_INDEXES);
093                    }
094    
095                    long classNameId = PortalUtil.getClassNameId(
096                            "com.liferay.portlet.dynamicdatamapping.DDMStructure");
097    
098                    try {
099                            runSQL("update DDMTemplate set classNameId = " + classNameId);
100                    }
101                    catch (Exception e) {
102                            if (_log.isWarnEnabled()) {
103                                    _log.warn(e, e);
104                            }
105                    }
106            }
107    
108            protected void updateStructure(
109                            long structureId, String structureKey, String xsd)
110                    throws Exception {
111    
112                    Connection con = null;
113                    PreparedStatement ps = null;
114                    ResultSet rs = null;
115    
116                    try {
117                            con = DataAccess.getUpgradeOptimizedConnection();
118    
119                            ps = con.prepareStatement(
120                                    "update DDMStructure set structureKey = ?, xsd = ? where " +
121                                            "structureId = ?");
122    
123                            ps.setString(1, structureKey);
124                            ps.setString(2, xsd);
125                            ps.setLong(3, structureId);
126    
127                            ps.executeUpdate();
128                    }
129                    catch (SQLException sqle) {
130                            if (_log.isWarnEnabled()) {
131                                    _log.warn(sqle, sqle);
132                            }
133                    }
134                    finally {
135                            DataAccess.cleanUp(con, ps, rs);
136                    }
137            }
138    
139            protected void updateStructures() throws Exception {
140                    Connection con = null;
141                    PreparedStatement ps = null;
142                    ResultSet rs = null;
143    
144                    try {
145                            con = DataAccess.getUpgradeOptimizedConnection();
146    
147                            ps = con.prepareStatement(
148                                    "select structureId, structureKey, xsd from DDMStructure");
149    
150                            rs = ps.executeQuery();
151    
152                            while (rs.next()) {
153                                    long structureId = rs.getLong("structureId");
154                                    String structureKey = rs.getString("structureKey");
155                                    String xsd = rs.getString("xsd");
156    
157                                    if (Validator.isNull(structureKey)) {
158                                            structureKey = String.valueOf(System.currentTimeMillis());
159                                    }
160                                    else {
161                                            structureKey = StringUtil.toUpperCase(structureKey.trim());
162                                    }
163    
164                                    updateStructure(
165                                            structureId, structureKey, updateXSD(xsd, structureKey));
166                            }
167                    }
168                    finally {
169                            DataAccess.cleanUp(con, ps, rs);
170                    }
171            }
172    
173            protected void updateStructuresClassNameId() throws Exception {
174                    Connection con = null;
175                    PreparedStatement ps = null;
176                    ResultSet rs = null;
177    
178                    try {
179                            con = DataAccess.getUpgradeOptimizedConnection();
180    
181                            ps = con.prepareStatement(
182                                    "update DDMStructure set classNameId = ? where " +
183                                            "classNameId = ?");
184    
185                            ps.setLong(1, PortalUtil.getClassNameId(DLFileEntryMetadata.class));
186                            ps.setLong(2, PortalUtil.getClassNameId(DLFileEntry.class));
187    
188                            ps.executeUpdate();
189                    }
190                    catch (SQLException sqle) {
191                            if (_log.isWarnEnabled()) {
192                                    _log.warn(sqle, sqle);
193                            }
194                    }
195                    finally {
196                            DataAccess.cleanUp(con, ps, rs);
197                    }
198            }
199    
200            protected void updateTemplate(
201                            long templateId, String templateKey, String script)
202                    throws Exception {
203    
204                    Connection con = null;
205                    PreparedStatement ps = null;
206                    ResultSet rs = null;
207    
208                    try {
209                            con = DataAccess.getUpgradeOptimizedConnection();
210    
211                            ps = con.prepareStatement(
212                                    "update DDMTemplate set templateKey = ?, script = ? where " +
213                                            "templateId = ?");
214    
215                            ps.setString(1, templateKey);
216                            ps.setString(2, script);
217                            ps.setLong(3, templateId);
218    
219                            ps.executeUpdate();
220                    }
221                    finally {
222                            DataAccess.cleanUp(con, ps, rs);
223                    }
224            }
225    
226            protected void updateTemplates() throws Exception {
227                    Connection con = null;
228                    PreparedStatement ps = null;
229                    ResultSet rs = null;
230    
231                    try {
232                            con = DataAccess.getUpgradeOptimizedConnection();
233    
234                            ps = con.prepareStatement(
235                                    "select templateId, templateKey, script from DDMTemplate " +
236                                            "where language = 'xsd'");
237    
238                            rs = ps.executeQuery();
239    
240                            while (rs.next()) {
241                                    long templateId = rs.getLong("templateId");
242                                    String templateKey = rs.getString("templateKey");
243                                    String script = rs.getString("script");
244    
245                                    if (Validator.isNull(templateKey)) {
246                                            templateKey = String.valueOf(System.currentTimeMillis());
247                                    }
248                                    else {
249                                            templateKey = StringUtil.toUpperCase(templateKey.trim());
250                                    }
251    
252                                    updateTemplate(
253                                            templateId, templateKey,
254                                            updateXSD(script, StringPool.BLANK));
255                            }
256                    }
257                    finally {
258                            DataAccess.cleanUp(con, ps, rs);
259                    }
260            }
261    
262            protected String updateXSD(String xsd, String structureKey)
263                    throws Exception {
264    
265                    Document document = SAXReaderUtil.read(xsd);
266    
267                    Element rootElement = document.getRootElement();
268    
269                    List<Element> dynamicElementElements = rootElement.elements(
270                            "dynamic-element");
271    
272                    for (Element dynamicElementElement : dynamicElementElements) {
273                            updateXSDDynamicElement(dynamicElementElement, structureKey);
274                    }
275    
276                    return XMLUtil.formatXML(document);
277            }
278    
279            protected void updateXSDDynamicElement(
280                    Element element, String structureKey) {
281    
282                    Element metadataElement = element.element("meta-data");
283    
284                    updateMetadataElement(
285                            metadataElement,
286                            new String[] {
287                                    "multiple", "name", "readOnly", "repeatable", "required",
288                                    "showLabel", "type", "width"
289                            },
290                            new String[] {
291                                    "acceptFiles", "displayChildLabelAsValue", "fieldCssClass",
292                                    "folder"
293                            });
294    
295                    if (StringUtil.equalsIgnoreCase(
296                                    structureKey, RawMetadataProcessor.TIKA_RAW_METADATA)) {
297    
298                            element.addAttribute("indexType", "text");
299                    }
300    
301                    List<Element> dynamicElementElements = element.elements(
302                            "dynamic-element");
303    
304                    for (Element dynamicElementElement : dynamicElementElements) {
305                            updateXSDDynamicElement(dynamicElementElement, structureKey);
306                    }
307            }
308    
309            private static final Log _log = LogFactoryUtil.getLog(
310                    UpgradeDynamicDataMapping.class);
311    
312    }