001package fr.ifremer.adagio.synchro.intercept;
002
003/*
004 * #%L
005 * SIH-Adagio :: Synchronization
006 * $Id:$
007 * $HeadURL:$
008 * %%
009 * Copyright (C) 2012 - 2014 Ifremer
010 * %%
011 * This program is free software: you can redistribute it and/or modify
012 * it under the terms of the GNU Affero General Public License as published by
013 * the Free Software Foundation, either version 3 of the License, or
014 * (at your option) any later version.
015 * 
016 * This program is distributed in the hope that it will be useful,
017 * but WITHOUT ANY WARRANTY; without even the implied warranty of
018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
019 * GNU General Public License for more details.
020 * 
021 * You should have received a copy of the GNU Affero General Public License
022 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
023 * #L%
024 */
025
026import java.sql.SQLException;
027import java.util.List;
028import java.util.Map;
029
030import org.apache.commons.lang3.StringUtils;
031import org.hibernate.tool.hbm2ddl.TableMetadata;
032
033import com.google.common.base.Preconditions;
034
035import fr.ifremer.adagio.synchro.dao.SynchroTableDao;
036import fr.ifremer.adagio.synchro.meta.SynchroDatabaseMetadata;
037import fr.ifremer.adagio.synchro.meta.SynchroJoinMetadata;
038import fr.ifremer.adagio.synchro.meta.SynchroTableMetadata;
039import fr.ifremer.adagio.synchro.service.SynchroContext;
040
041public class SynchroInterceptorBase implements SynchroInterceptorChain {
042    private SynchroInterceptor next;
043
044    private SynchroContext context;
045
046    public SynchroInterceptorBase() {
047        this.next = null;
048        this.context = null;
049    }
050
051    public SynchroInterceptorBase(SynchroInterceptor next) {
052        this.next = next;
053        this.context = null;
054    }
055
056    public boolean apply(SynchroDatabaseMetadata meta, TableMetadata table) {
057        return false;
058    }
059
060    @Override
061    public void setNext(SynchroInterceptor next) {
062        this.next = next;
063    }
064
065    public SynchroInterceptor getNext() {
066        return this.next;
067    }
068
069    @Override
070    public final void onRead(Object[] data, SynchroTableDao dao) throws SQLException {
071        doOnRead(data, dao);
072
073        if (next != null) {
074            next.onRead(data, dao);
075        }
076    }
077
078    @Override
079    public final void onWrite(Object[] data, SynchroTableDao dao, SynchroWriteBuffer buffer) throws SQLException {
080        doOnWrite(data, dao, buffer);
081
082        if (next != null) {
083            next.onWrite(data, dao, buffer);
084        }
085    }
086
087    @Override
088    public Map<List<Object>, Object[]> transformExtraLocalData(
089            SynchroTableDao localDao, SynchroTableDao remoteDao,
090            Map<List<Object>, Object[]> extraRows) throws SQLException {
091        Map<List<Object>, Object[]> result = doTransformExtraLocalData(localDao, remoteDao, extraRows);
092
093        if (next != null) {
094            result = next.transformExtraLocalData(localDao, remoteDao, result);
095        }
096        return result;
097    }
098
099    @Override
100    public final String onCreateSelectQuery(SynchroTableMetadata table, String queryName, String sql) {
101        String newSql = doCreateSelectQuery(table, queryName, sql);
102
103        if (next != null) {
104            newSql = next.onCreateSelectQuery(
105                    table,
106                    queryName,
107                    newSql != null ? newSql : sql);
108        }
109        return newSql;
110    }
111
112    public final void onTableLoad(SynchroTableMetadata table) {
113        doTableLoad(table);
114        if (next != null) {
115            next.onTableLoad(table);
116        }
117    }
118
119    public final void onJoinLoad(SynchroTableMetadata table, SynchroJoinMetadata join) {
120        doJoinLoad(table, join);
121        if (next != null) {
122            next.onJoinLoad(table, join);
123        }
124    }
125
126    @Override
127    public boolean enableOnRead() {
128        return false;
129    }
130
131    @Override
132    public boolean enableOnWrite() {
133        return false;
134    }
135
136    @Override
137    public void setContext(SynchroContext context) {
138        this.context = context;
139    }
140
141    protected SynchroContext getContext() {
142        return this.context;
143    }
144
145    /* -- protected method -- */
146
147    protected void doTableLoad(SynchroTableMetadata table) {
148    }
149
150    protected void doJoinLoad(SynchroTableMetadata table, SynchroJoinMetadata join) {
151    }
152
153    protected String doCreateSelectQuery(SynchroTableMetadata table, String queryName, String sql) {
154        String[] clauses = sql.split("(FROM)|(WHERE)");
155        Preconditions.checkArgument(
156                clauses.length == 2 || clauses.length == 3,
157                String.format("Bad sql query: [%s]. Expected: SELECT <...> FROM <...> WHERE <...>", sql));
158        String selectClause = clauses[0];
159        String fromClause = clauses[1];
160        String whereClause = clauses.length == 3 ? clauses[2] : null;
161        return doCreateSelectQuery(table, selectClause, fromClause, whereClause, queryName);
162    }
163
164    /**
165     * Default implementation, that return the same SQL query.
166     * This method should be override by subclasses
167     * 
168     * @param table
169     * @param selectClause
170     * @param fromClause
171     * @param whereClause
172     * @param queryName
173     * @return
174     */
175    protected String doCreateSelectQuery(SynchroTableMetadata table,
176            String selectClause,
177            String fromClause,
178            String whereClause,
179            String queryName) {
180        StringBuilder sb = new StringBuilder(selectClause).append(" FROM ").append(fromClause);
181        if (StringUtils.isNotBlank(whereClause)) {
182            sb.append(" WHERE ").append(whereClause);
183        }
184        return sb.toString();
185    }
186
187    protected void doOnRead(Object[] data, SynchroTableDao dao) throws SQLException {
188
189    }
190
191    protected void doOnWrite(Object[] data, SynchroTableDao dao, SynchroWriteBuffer buffer) throws SQLException {
192
193    }
194
195    protected Map<List<Object>, Object[]> doTransformExtraLocalData(
196            SynchroTableDao localDao, SynchroTableDao remoteDao,
197            Map<List<Object>, Object[]> extraRows) throws SQLException {
198        return extraRows;
199    }
200
201}