1   /*
2    * Copyright 2003 - 2013 The eFaps Team
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   * Revision:        $Rev$
17   * Last Changed:    $Date$
18   * Last Changed By: $Author$
19   */
20  
21  
22  package org.efaps.db;
23  
24  import java.sql.ResultSet;
25  import java.sql.SQLException;
26  import java.sql.Statement;
27  import java.util.ArrayList;
28  import java.util.List;
29  import java.util.Map.Entry;
30  import java.util.UUID;
31  
32  import org.efaps.admin.datamodel.SQLTable;
33  import org.efaps.admin.datamodel.Type;
34  import org.efaps.db.transaction.ConnectionResource;
35  import org.efaps.db.wrapper.SQLSelect;
36  import org.efaps.util.EFapsException;
37  import org.efaps.util.cache.CacheReloadException;
38  
39  
40  /**
41   * Query that returns a list of instances.
42   *
43   * @author The eFaps Team
44   * @version $Id$
45   */
46  public class InstanceQuery
47      extends AbstractObjectQuery<Instance>
48  {
49      /**
50       * Constructor setting the type by his UUID.
51       * @param _typeUUI UUID of the Type the query is based on
52       * @throws CacheReloadException on error
53       */
54      public InstanceQuery(final UUID _typeUUI)
55          throws CacheReloadException
56      {
57          this(Type.get(_typeUUI));
58      }
59  
60      /**
61       * Constructor setting the type.
62       * @param _type TYpe the query is based on
63       */
64      public InstanceQuery(final Type _type)
65      {
66          super(_type);
67      }
68  
69      /**
70       * Execute the Query.
71       * @return this
72       * @throws EFapsException
73       * TODO Accesscheck
74       */
75      @Override
76      public List<Instance> execute()
77          throws EFapsException
78      {
79          return executeWithoutAccessCheck();
80      }
81  
82      /**
83       * The instance method executes the query without an access check.
84       *
85       * @return true if the query contains values, else false
86       * @throws EFapsException on error
87       */
88      @Override
89      public List<Instance> executeWithoutAccessCheck()
90          throws EFapsException
91      {
92          prepareQuery();
93          executeOneCompleteStmt(createSQLStatement());
94          return getValues();
95      }
96  
97      /**
98       * Create the SQL statement.
99       * @return StringBuilder containing the statement
100      * @throws EFapsException on error
101      */
102     protected String createSQLStatement()
103         throws EFapsException
104     {
105         final SQLSelect select = new SQLSelect()
106             .column(0, "ID")
107             .from(getBaseType().getMainTable().getSqlTable(), 0);
108 
109         // if the main table has a column for the type it is selected also
110         if (getBaseType().getMainTable().getSqlColType() != null) {
111             select.column(0, getBaseType().getMainTable().getSqlColType());
112         }
113         // add child tables
114         if (getSqlTable2Index().size() > 0) {
115             for (final Entry<SQLTable, Integer> entry : getSqlTable2Index().entrySet()) {
116                 if (entry.getValue() > 0) {
117                     select.leftJoin(entry.getKey().getSqlTable(), entry.getValue(), "ID", 0, "ID");
118                 }
119             }
120         }
121         select.addSection(getWhere());
122         select.addSection(getOrderBy());
123         select.addSection(getLimit());
124 
125         return select.getSQL();
126     }
127 
128     /**
129      * Execute the actual statement against the database.
130      * @param _complStmt        Statment to be executed
131      * @return true if executed with success
132      * @throws EFapsException on error
133      */
134     protected boolean executeOneCompleteStmt(final String _complStmt)
135         throws EFapsException
136     {
137         final boolean ret = false;
138         ConnectionResource con = null;
139         try {
140             con = Context.getThreadContext().getConnectionResource();
141 
142             AbstractObjectQuery.LOG.debug("Executing SQL: {}", _complStmt);
143 
144             final Statement stmt = con.getConnection().createStatement();
145 
146             final ResultSet rs = stmt.executeQuery(_complStmt.toString());
147             final List<Object[]> values = new ArrayList<Object[]>();
148             while (rs.next()) {
149                 final long id = rs.getLong(1);
150                 Long typeId = null;
151                 if (getBaseType().getMainTable().getSqlColType() != null) {
152                     typeId = rs.getLong(2);
153                 }
154                 values.add(new Object[]{id, typeId});
155             }
156             rs.close();
157             stmt.close();
158             con.commit();
159             for (final Object[] row: values) {
160                 final Long id = (Long) row[0];
161                 final Long typeId = (Long) row[1];
162                 getValues().add(Instance.get(typeId == null ? getBaseType() : Type.get(typeId), id));
163             }
164         } catch (final SQLException e) {
165             throw new EFapsException(InstanceQuery.class, "executeOneCompleteStmt", e);
166         } finally {
167             if (con != null && con.isOpened()) {
168                 con.abort();
169             }
170         }
171         return ret;
172     }
173 }