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.util.Collection;
027import java.util.List;
028import java.util.ServiceLoader;
029
030import org.hibernate.dialect.Dialect;
031import org.hibernate.tool.hbm2ddl.TableMetadata;
032
033import com.google.common.base.Predicate;
034import com.google.common.collect.Collections2;
035import com.google.common.collect.Lists;
036
037import fr.ifremer.adagio.synchro.SynchroTechnicalException;
038import fr.ifremer.adagio.synchro.meta.SynchroDatabaseMetadata;
039import fr.ifremer.adagio.synchro.service.SynchroContext;
040
041public class SynchroInterceptorUtils {
042
043    private SynchroInterceptorUtils() {
044        // helper class
045    }
046
047    public static <T, U extends SynchroInterceptor> List<U> load(Class<U> clazz, SynchroContext context) {
048        List<U> result = Lists.newArrayList();
049
050        ServiceLoader<U> loader = ServiceLoader.load(clazz);
051        for (U interceptor : loader) {
052            // Set the current context
053            interceptor.setContext(context);
054
055            result.add(interceptor);
056        }
057        return result;
058    }
059
060    public static <T, U extends SynchroInterceptor> Collection<U> filter(List<U> interceptors, final SynchroDatabaseMetadata meta,
061            final TableMetadata table) {
062        // Retrieve overrides to apply on this table
063        Collection<U> result = Collections2.filter(
064                interceptors,
065                new Predicate<SynchroInterceptor>() {
066                    public boolean apply(SynchroInterceptor interceptor) {
067                        return interceptor.apply(meta, table);
068                    }
069                });
070        return result;
071    }
072
073    public static <T, U extends SynchroInterceptor> U chain(List<U> interceptors,
074            final SynchroDatabaseMetadata meta,
075            final TableMetadata table,
076            Class<? extends SynchroInterceptorChain> chainClazz) {
077        Collection<U> filteredInterceptors = filter(interceptors, meta, table);
078
079        try {
080            return (U) createChain(filteredInterceptors, chainClazz);
081        } catch (InstantiationException e) {
082            throw new SynchroTechnicalException("Could not instantiate interceptor : " + e.getMessage(), e);
083        } catch (IllegalAccessException e) {
084            throw new SynchroTechnicalException("Could not instantiate interceptor : " + e.getMessage(), e);
085        }
086    }
087
088    public static <T, U extends SynchroInterceptor, V extends SynchroInterceptorChain> U chain(Collection<U> interceptors,
089            Class<V> chainClazz) {
090        try {
091            return (U) createChain(interceptors, chainClazz);
092        } catch (InstantiationException e) {
093            throw new SynchroTechnicalException("Could not instantiate interceptor : " + e.getMessage(), e);
094        } catch (IllegalAccessException e) {
095            throw new SynchroTechnicalException("Could not instantiate interceptor : " + e.getMessage(), e);
096        }
097    }
098
099    protected static <T, U extends SynchroInterceptor> SynchroInterceptorChain createChain(Collection<U> interceptors,
100            Class<? extends SynchroInterceptorChain> chainClazz) throws InstantiationException, IllegalAccessException {
101        SynchroInterceptorChain result = null;
102        SynchroInterceptorChain previous = null;
103        for (U interceptor : interceptors) {
104            SynchroInterceptorChain newChain = null;
105            if (interceptor instanceof SynchroInterceptorChain) {
106                newChain = (SynchroInterceptorChain) interceptor;
107            }
108            else {
109                newChain = encapsulate(interceptor, chainClazz);
110            }
111            if (result == null) {
112                result = newChain;
113            }
114            else if (previous != null) {
115                previous.setNext((U) newChain);
116            }
117            previous = newChain;
118        }
119        return result;
120    }
121
122    protected static <T, U extends SynchroInterceptor> SynchroInterceptorChain encapsulate(U delegate,
123            Class<? extends SynchroInterceptorChain> chainClass) throws InstantiationException, IllegalAccessException {
124        SynchroInterceptorChain chain = (SynchroInterceptorChain) chainClass.newInstance();
125        chain.setNext(delegate);
126        return chain;
127    }
128}