001/*
002 * HA-JDBC: High-Availability JDBC
003 * Copyright (C) 2013  Paul Ferraro
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Lesser General Public License as published by
007 * the Free Software Foundation, either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Lesser General Public License for more details.
014 *
015 * You should have received a copy of the GNU Lesser General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018package net.sf.hajdbc.io;
019
020import java.io.IOException;
021import java.io.InputStream;
022import java.io.Reader;
023import java.util.HashMap;
024import java.util.LinkedList;
025import java.util.List;
026import java.util.Map;
027
028/**
029 * A sink type independent registry for input sinks.
030 * @author Paul Ferraro
031 * @param <S> sink type
032 */
033public class InputSinkRegistryImpl<S> implements InputSinkRegistry<S>
034{
035        private final List<S> sinks = new LinkedList<S>();
036        private final Map<Class<?>, InputSinkChannel<?, S>> channels = new HashMap<Class<?>, InputSinkChannel<?, S>>();
037        private final InputSinkStrategy<S> strategy;
038        
039        public InputSinkRegistryImpl(InputSinkStrategy<S> strategy)
040        {
041                this.addInputChannel(InputStream.class, strategy.createInputStreamChannel());
042                this.addInputChannel(Reader.class, strategy.createReaderChannel());
043                this.strategy = strategy;
044        }
045        
046        private <I> void addInputChannel(Class<I> inputClass, InputSinkChannel<I, S> channel)
047        {
048                this.channels.put(inputClass, channel);
049        }
050        
051        S addInputSink(S sink)
052        {
053                this.sinks.add(sink);
054                return sink;
055        }
056        
057        @Override
058        public <I> InputSinkChannel<I, S> get(Class<I> inputClass)
059        {
060                final InputSinkChannel<I, S> channel = (InputSinkChannel<I, S>) this.channels.get(inputClass);
061                
062                return (channel == null) ? null : new InputSinkChannel<I, S>()
063                {
064                        @Override
065                        public S write(I input) throws IOException
066                        {
067                                return InputSinkRegistryImpl.this.addInputSink(channel.write(input));
068                        }
069
070                        @Override
071                        public I read(S sink) throws IOException
072                        {
073                                return channel.read(sink);
074                        }       
075                };
076        }
077
078        @Override
079        public void close()
080        {
081                for (S sink: this.sinks)
082                {
083                        this.strategy.close(sink);
084                }
085                this.sinks.clear();
086        }
087}