View Javadoc

1   /*
2    * Copyright 2012-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.properties.spi.config.ds;
17  
18  import java.sql.Connection;
19  import java.sql.ResultSet;
20  import java.sql.SQLException;
21  import java.util.Iterator;
22  import java.util.NoSuchElementException;
23  
24  import javax.annotation.concurrent.NotThreadSafe;
25  
26  import de.smartics.properties.api.config.domain.Property;
27  import de.smartics.properties.api.config.domain.PropertyCollection;
28  import de.smartics.properties.api.config.domain.PropertyLocation;
29  
30  /**
31   * Implementation of {@link PropertyCollection} based on accessing a data
32   * source.
33   */
34  @NotThreadSafe
35  public final class DsPropertyCollection implements PropertyCollection
36  {
37    // ********************************* Fields *********************************
38  
39    // --- constants ------------------------------------------------------------
40  
41    // --- members --------------------------------------------------------------
42  
43    /**
44     * The identifier of the data source the properties are read from.
45     */
46    private final String dataSourceId;
47  
48    /**
49     * The underlying connection of the result set.
50     */
51    private final Connection connection;
52  
53    /**
54     * The properties to iterate over.
55     */
56    private final ResultSet resultSet;
57  
58    // ****************************** Initializer *******************************
59  
60    // ****************************** Constructors ******************************
61  
62    /**
63     * Default constructor.
64     *
65     * @param dataSourceId the identifier of the data source the properties are
66     *          read from.
67     * @param connection the underlying connection of the result set.
68     * @param resultSet the properties to iterate over.
69     */
70    public DsPropertyCollection(final String dataSourceId,
71        final Connection connection, final ResultSet resultSet)
72    {
73      this.dataSourceId = dataSourceId;
74      this.connection = connection;
75      this.resultSet = resultSet;
76    }
77  
78    // ****************************** Inner Classes *****************************
79  
80    /**
81     * Maps the result set iteration to a Java iterator.
82     */
83    private final class ResultSetIterator implements Iterator<Property>
84    {
85      // ******************************** Fields ********************************
86  
87      // --- constants ----------------------------------------------------------
88  
89      // --- members ------------------------------------------------------------
90      /**
91       * A reference to the next property to return.
92       */
93      private Property nextProperty;
94  
95      // ***************************** Initializer ******************************
96  
97      // ***************************** Constructors *****************************
98  
99      // ***************************** Inner Classes ****************************
100 
101     // ******************************** Methods *******************************
102 
103     // --- init ---------------------------------------------------------------
104 
105     // --- get&set ------------------------------------------------------------
106 
107     // --- business -----------------------------------------------------------
108 
109     @Override
110     public boolean hasNext()
111     {
112       provideProperty();
113       return nextProperty != null;
114     }
115 
116     @Override
117     public Property next()
118     {
119       provideProperty();
120 
121       if (nextProperty == null)
122       {
123         throw new NoSuchElementException(
124             "No further elements in collection from data source '"
125                 + dataSourceId + "'.");
126       }
127 
128       final Property currentProperty = nextProperty;
129       nextProperty = null;
130       return currentProperty;
131     }
132 
133     /**
134      * {@inheritDoc}
135      * <p>
136      * Not supported by this implementation.
137      * </p>
138      *
139      * @throws UnsupportedOperationException always.
140      */
141     @Override
142     public void remove() throws UnsupportedOperationException
143     {
144       throw new UnsupportedOperationException("Remove not supported.");
145     }
146 
147     private void provideProperty()
148     {
149       if (nextProperty == null)
150       {
151         try
152         {
153           if (resultSet.next())
154           {
155             final String name = resultSet.getString(1);
156             final String value = resultSet.getString(2);
157             nextProperty =
158                 new Property(new PropertyLocation(dataSourceId), name, value);
159           }
160           else
161           {
162             close();
163           }
164         }
165         catch (final SQLException e)
166         {
167           close();
168           throw new IllegalStateException(
169               "Cannot read next property from data source '" + dataSourceId
170                   + "'.");
171 
172         }
173       }
174     }
175 
176     // --- object basics ------------------------------------------------------
177   }
178 
179   // ********************************* Methods ********************************
180 
181   // --- init -----------------------------------------------------------------
182 
183   // --- get&set --------------------------------------------------------------
184 
185   // --- business -------------------------------------------------------------
186 
187   /**
188    * {@inheritDoc}
189    *
190    * @see java.lang.Iterable#iterator()
191    */
192   @Override
193   public Iterator<Property> iterator()
194   {
195     return new ResultSetIterator();
196   }
197 
198   /**
199    * Closes the collection to release the underlying connection.
200    * <p>
201    * The connection is automatically closed when the iterator reaches the last
202    * element.
203    * </p>
204    */
205   @Override
206   public void close()
207   {
208     try
209     {
210       if (!connection.isClosed())
211       {
212         connection.close();
213       }
214     }
215     catch (final SQLException e)
216     {
217       // Ignore
218     }
219   }
220 
221   // --- object basics --------------------------------------------------------
222 
223 }