@@ -112,22 +112,33 @@ void fillNamesAndTypes(IloTupleSchema schema, String[] names, Type[] types) {
112112 * Overrides the IloCustomOplDataSource method to read data when the model
113113 * is generated.
114114 */
115+ @ Override
115116 public void customRead () {
116117 long startTime = System .currentTimeMillis ();
117- System .out .println ("Reading elements from database" );
118- Properties prop = _configuration .getReadQueries ();
119- Enumeration <?> propertyNames = prop .propertyNames ();
120- while (propertyNames .hasMoreElements ()) {
121- String name = (String ) propertyNames .nextElement ();
122- String query = prop .getProperty (name );
123- System .out .println ("Reading " + name + " using \" " + query + "\" " );
124- customRead (name , query );
118+ try {
119+ System .out .println ("Reading elements from database" );
120+ Properties prop = _configuration .getReadQueries ();
121+ Enumeration <?> propertyNames = prop .propertyNames ();
122+ while (propertyNames .hasMoreElements ()) {
123+ String name = (String ) propertyNames .nextElement ();
124+ String query = prop .getProperty (name );
125+ System .out .println ("Reading " + name + " using \" " + query + "\" " );
126+ customRead (name , query );
127+ }
128+ long endTime = System .currentTimeMillis ();
129+ System .out .println ("Done (" + (endTime - startTime )/1000.0 + " s)" );
130+ }
131+ catch (SQLException e ) {
132+ // Since the superclass's method signature does not allow us to
133+ // throw an exception from here, we have to wrap the exception.
134+ long endTime = System .currentTimeMillis ();
135+ System .err .println (e .getMessage () + " (after " + (endTime - startTime )/1000.0 + " s)" );
136+ e .printStackTrace ();
137+ throw new RuntimeException (e );
125138 }
126- long endTime = System .currentTimeMillis ();
127- System .out .println ("Done (" + (endTime - startTime )/1000.0 + " s)" );
128139 }
129140
130- public void customRead (String name , String query ) {
141+ public void customRead (String name , String query ) throws SQLException {
131142 IloOplElementDefinition def = _def .getElementDefinition (name );
132143 Type type = def .getElementDefinitionType ();
133144 Type leaf = def .getLeaf ().getElementDefinitionType ();
@@ -139,17 +150,105 @@ public void customRead(String name, String query) {
139150 readSet (leaf , name , query );
140151 }
141152 }
153+ else if ( type == Type .INTEGER || type == Type .FLOAT || type == Type .STRING ) {
154+ readValue (name , query );
155+ }
156+ else
157+ throw new IllegalArgumentException ("Cannot read element " + name + " of type " + type );
142158 }
143159
144- public void readSet (Type leaf , String name , String query ) {
160+ /** Helper class to execute queries in an exception safe way.
161+ * Use the class via the following template:
162+ * <pre>
163+ final RunQuery q = new RunQuery("SELECT * FROM table;");
164+ try {
165+ ResultSet rs = q.getResult();
166+ ...
167+ }
168+ finally {
169+ q.close();
170+ }
171+ </pre>
172+ * This will correctly clean up and release all resources no matter whether
173+ * an exception is throw or not.
174+ */
175+ private final class RunQuery {
176+ private Connection conn = null ;
177+ private Statement stmt = null ;
178+ private ResultSet rs = null ;
179+ public RunQuery (String query ) throws SQLException {
180+ Connection conn = DriverManager .getConnection (_configuration .getUrl (),
181+ _configuration .getUser (),
182+ _configuration .getPassword ());
183+ Statement stmt = null ;
184+ ResultSet rs = null ;
185+ try {
186+ stmt = conn .createStatement ();
187+ rs = stmt .executeQuery (query );
188+ // Everything worked without problem. Transfer ownership of
189+ // the objects to the newly constructed instance.
190+ this .conn = conn ; conn = null ;
191+ this .stmt = stmt ; stmt = null ;
192+ this .rs = rs ; rs = null ;
193+ }
194+ finally {
195+ if ( rs != null ) rs .close ();
196+ if ( stmt != null ) stmt .close ();
197+ if ( conn != null ) conn .close ();
198+ }
199+ }
200+ public void close () throws SQLException {
201+ rs .close ();
202+ stmt .close ();
203+ conn .close ();
204+ }
205+ ResultSet getResult () { return rs ; }
206+ }
207+
208+ /** Read the scalar value for <code>name</code> from <code>query</code>.
209+ * <b>Note:</b> the function will just use the first value produced by
210+ * <code>query</code> and assign that to the element identified
211+ * by <code>name</code>. If the query produces more than one
212+ * value the surplus values are ignored.
213+ * @param name The name of the element to fill.
214+ * @param query The SQL query that produces the data for <code>name</code>.
215+ * @throws SQLException if querying the database fails or the query does
216+ * not produce at least one value.
217+ */
218+ public void readValue (String name , String query ) throws SQLException {
219+ IloOplElementDefinition def = _def .getElementDefinition (name );
145220 IloOplDataHandler handler = getDataHandler ();
221+ final RunQuery q = new RunQuery (query );
146222 try {
147- Connection conn = DriverManager .getConnection (_configuration .getUrl (),
148- _configuration .getUser (),
149- _configuration .getPassword ());
150- Statement stmt = conn .createStatement ();
151- ResultSet rs = stmt .executeQuery (query );
223+ ResultSet rs = q .getResult ();
224+ rs .next ();
225+ handler .startElement (name );
226+ Type type = def .getElementDefinitionType ();
227+ if (type == Type .INTEGER ) {
228+ handler .addIntItem (rs .getInt (1 ));
229+ }
230+ else if (type == Type .FLOAT ) {
231+ handler .addNumItem (rs .getDouble (1 ));
232+ }
233+ else if (type == Type .STRING ) {
234+ handler .addStringItem (rs .getString (1 ));
235+ }
236+ else
237+ throw new IllegalArgumentException ("Cannot load element " + name + " of type " + type );
238+ handler .endElement ();
239+ }
240+ finally {
241+ // We don't use try-with-resources so that we can compile
242+ // with pre-1.8 compilers as well.
243+ q .close ();
244+ }
245+ }
152246
247+ public void readSet (Type leaf , String name , String query ) throws SQLException {
248+ IloOplDataHandler handler = getDataHandler ();
249+ final RunQuery q = new RunQuery (query );
250+ try {
251+ ResultSet rs = q .getResult ();
153252 handler .startElement (name );
154253 handler .startSet ();
155254
@@ -163,32 +262,27 @@ else if (leaf == Type.STRING)
163262 }
164263 handler .endSet ();
165264 handler .endElement ();
166- rs .close ();
167- stmt .close ();
168- conn .close ();
169- } catch (SQLException e ) {
170- e .printStackTrace ();
265+ }
266+ finally {
267+ q .close ();
171268 }
172269 }
173270
174- public void readTupleSet (String name , String query ) {
271+ public void readTupleSet (String name , String query ) throws SQLException {
175272 IloOplDataHandler handler = getDataHandler ();
176- try {
177- IloOplElement elt = handler .getElement (name );
178- ilog .opl_core .cppimpl .IloTupleSet tupleSet = (ilog .opl_core .cppimpl .IloTupleSet ) elt .asTupleSet ();
179- IloTupleSchema schema = tupleSet .getSchema_cpp ();
180- int size = schema .getTotalColumnNumber ();
273+ IloOplElement elt = handler .getElement (name );
274+ ilog .opl_core .cppimpl .IloTupleSet tupleSet = (ilog .opl_core .cppimpl .IloTupleSet ) elt .asTupleSet ();
275+ IloTupleSchema schema = tupleSet .getSchema_cpp ();
276+ int size = schema .getTotalColumnNumber ();
181277
182- String [] oplFieldsName = new String [size ];
183- Type [] oplFieldsType = new Type [size ];
278+ String [] oplFieldsName = new String [size ];
279+ Type [] oplFieldsType = new Type [size ];
184280
185- fillNamesAndTypes (schema , oplFieldsName , oplFieldsType );
281+ fillNamesAndTypes (schema , oplFieldsName , oplFieldsType );
186282
187- Connection conn = DriverManager .getConnection (_configuration .getUrl (),
188- _configuration .getUser (),
189- _configuration .getPassword ());
190- Statement stmt = conn .createStatement ();
191- ResultSet rs = stmt .executeQuery (query );
283+ final RunQuery q = new RunQuery (query );
284+ try {
285+ ResultSet rs = q .getResult ();
192286
193287 handler .startElement (name );
194288 handler .startSet ();
@@ -208,12 +302,9 @@ public void readTupleSet(String name, String query) {
208302 }
209303 handler .endSet ();
210304 handler .endElement ();
211- rs .close ();
212- stmt .close ();
213- conn .close ();
214- } catch (SQLException e ) {
215- e .printStackTrace ();
216305 }
217-
306+ finally {
307+ q .close ();
308+ }
218309 }
219310};
0 commit comments