001/*
002 * HA-JDBC: High-Availability JDBC
003 * Copyright (C) 2012  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.balancer;
019
020import java.util.Collection;
021import java.util.Collections;
022import java.util.Iterator;
023import java.util.Set;
024import java.util.SortedSet;
025import java.util.TreeSet;
026
027import net.sf.hajdbc.Database;
028
029/**
030 * Thread-safe abstract balancer implementation that implements most of the Balancer interface, except {@link Balancer#next()}.
031 * Uses A copy-on-write algorithm for {@link #add(Object)}, {@link #remove(Object)}, and {@link #clear()}.
032 * Calls to {@link #iterator()} are non-blocking.
033 * 
034 * @author Paul Ferraro
035 * @param <Z>
036 * @param <D>
037 */
038public abstract class AbstractBalancer<Z, D extends Database<Z>> implements Balancer<Z, D>
039{
040        protected abstract Set<D> getDatabases();
041
042        /**
043         * {@inheritDoc}
044         * @see net.sf.hajdbc.balancer.Balancer#backups()
045         */
046        @Override
047        public Iterable<D> backups()
048        {
049                Iterator<D> databases = this.getDatabases().iterator();
050                
051                if (!databases.hasNext() || ((databases.next() != null) && !databases.hasNext())) return Collections.emptySet();
052                
053                D database = databases.next();
054                
055                if (!databases.hasNext()) return Collections.singleton(database);
056                
057                SortedSet<D> backups = new TreeSet<D>();
058                
059                backups.add(database);
060                
061                do
062                {
063                        backups.add(databases.next());
064                }
065                while (databases.hasNext());
066
067                return backups;
068        }
069        
070        /**
071         * {@inheritDoc}
072         * @see java.util.Set#iterator()
073         */
074        @Override
075        public Iterator<D> iterator()
076        {
077                return this.getDatabases().iterator();
078        }
079
080        /**
081         * {@inheritDoc}
082         * @see java.util.Set#contains(java.lang.Object)
083         */
084        @Override
085        public boolean contains(Object database)
086        {
087                return this.getDatabases().contains(database);
088        }
089
090        /**
091         * {@inheritDoc}
092         * @see java.util.Set#containsAll(java.util.Collection)
093         */
094        @Override
095        public boolean containsAll(Collection<?> databases)
096        {
097                return this.getDatabases().containsAll(databases);
098        }
099
100        /**
101         * {@inheritDoc}
102         * @see java.util.Set#isEmpty()
103         */
104        @Override
105        public boolean isEmpty()
106        {
107                return this.getDatabases().isEmpty();
108        }
109
110        /**
111         * {@inheritDoc}
112         * @see java.util.Set#size()
113         */
114        @Override
115        public int size()
116        {
117                return this.getDatabases().size();
118        }
119
120        /**
121         * {@inheritDoc}
122         * @see java.util.Set#toArray()
123         */
124        @Override
125        public Object[] toArray()
126        {
127                return this.getDatabases().toArray();
128        }
129
130        @Override
131        public <T> T[] toArray(T[] array)
132        {
133                return this.getDatabases().toArray(array);
134        }
135        
136        /**
137         * {@inheritDoc}
138         * @see java.lang.Object#equals(java.lang.Object)
139         */
140        @Override
141        public boolean equals(Object object)
142        {
143                if ((object == null) || !(object instanceof Collection)) return false;
144                
145                @SuppressWarnings("unchecked")
146                Collection<D> set = (Collection<D>) object;
147                
148                return this.getDatabases().equals(set);
149        }
150
151        /**
152         * {@inheritDoc}
153         * @see java.lang.Object#hashCode()
154         */
155        @Override
156        public int hashCode()
157        {
158                return this.getDatabases().hashCode();
159        }
160
161        @Override
162        public String toString()
163        {
164                return this.getDatabases().toString();
165        }
166}