001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Arnaud Kervern
018 *     Florent Guillaume
019 */
020package org.nuxeo.ecm.core.storage.sql.jdbc;
021
022import java.sql.SQLException;
023import java.util.ArrayList;
024import java.util.List;
025
026import org.apache.commons.logging.Log;
027import org.apache.commons.logging.LogFactory;
028import org.nuxeo.ecm.core.storage.sql.jdbc.db.Column;
029import org.nuxeo.ecm.core.storage.sql.jdbc.dialect.SQLStatement.ListCollector;
030
031/**
032 * Helper to provide SQL migration calls while adding a column.
033 *
034 * @since 5.4.2
035 */
036public class TableUpgrader {
037
038    protected static class TableUpgrade {
039        public final String tableKey;
040
041        public final String columnName;
042
043        public final String sqlProcedure;
044
045        public final String testProp;
046
047        public TableUpgrade(String tableKey, String columnName, String sqlProcedure, String testProp) {
048            this.tableKey = tableKey;
049            this.columnName = columnName;
050            this.sqlProcedure = sqlProcedure;
051            this.testProp = testProp;
052        }
053    }
054
055    protected List<TableUpgrade> tableUpgrades = new ArrayList<TableUpgrade>();
056
057    private JDBCMapper mapper;
058
059    private static final Log log = LogFactory.getLog(TableUpgrader.class);
060
061    public TableUpgrader(JDBCMapper mapper) {
062        this.mapper = mapper;
063    }
064
065    /**
066     * Add a couple table/column associated with a sql procedure to be executed when the column is added and a a test
067     * flag to force his execution.
068     *
069     * @param tableKey table name
070     * @param columnName desired added column
071     * @param sqlProcedure sql procedure name
072     * @param testProp test flag name
073     */
074    public void add(String tableKey, String columnName, String sqlProcedure, String testProp) {
075        tableUpgrades.add(new TableUpgrade(tableKey, columnName, sqlProcedure, testProp));
076    }
077
078    /**
079     * Check if there is an added column that match with a upgrade process. If one exists, it executes the associated
080     * sql in the category. If not, nothing happend.
081     *
082     * @param tableKey table name
083     * @param addedColumns list of added column
084     * @throws SQLException Exception thrown by JDBC
085     */
086    public void upgrade(String tableKey, List<Column> addedColumns, String ddlMode, ListCollector ddlCollector)
087            throws SQLException {
088        for (TableUpgrade upgrade : tableUpgrades) {
089            if (!upgrade.tableKey.equals(tableKey)) {
090                continue;
091            }
092            boolean doUpgrade;
093            if (addedColumns == null) {
094                // table created
095                doUpgrade = mapper.testProps.containsKey(upgrade.testProp);
096            } else {
097                // columns added
098                doUpgrade = false;
099                for (Column col : addedColumns) {
100                    if (col.getKey().equals(upgrade.columnName)) {
101                        doUpgrade = true;
102                        break;
103                    }
104                }
105            }
106            if (doUpgrade) {
107                log.info("Upgrading table: " + tableKey);
108                mapper.sqlInfo.executeSQLStatements(upgrade.sqlProcedure, ddlMode, mapper.connection, mapper.logger,
109                        ddlCollector);
110            }
111        }
112    }
113}