1   /*
2    * Copyright 2003 - 2014 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  package org.efaps.db.print;
22  
23  import java.sql.SQLException;
24  import java.util.ArrayList;
25  import java.util.Iterator;
26  import java.util.List;
27  
28  import org.efaps.admin.datamodel.Attribute;
29  import org.efaps.admin.datamodel.Type;
30  import org.efaps.db.Instance;
31  import org.efaps.db.wrapper.SQLSelect;
32  import org.efaps.util.EFapsException;
33  import org.efaps.util.cache.CacheReloadException;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  /**
38   * Select Part for <code>linkto[ATTRIBUTENAME]</code>.
39   * After invoking <code>{@link #next()}</code> currentinstance contains
40   * the instance it was linked to.
41   *
42   * @author The eFaps Team
43   * @version $Id$
44   */
45  public class LinkToSelectPart
46      extends AbstractSelectPart
47  {
48      /**
49       * Logging instance used in this class.
50       */
51      private static final Logger LOG = LoggerFactory.getLogger(OneSelect.class);
52  
53      /**
54       * Name of the Attribute the link to is based on.
55       */
56      private final String attrName;
57  
58      /**
59       * Type the {@link #attrName} belongs to.
60       */
61      private final Type type;
62  
63      /**
64       * index of the id Column.
65       */
66      private int idColumnIndex;
67  
68      /**
69       * index of the id Column.
70       */
71      private int typeColumnIndex = -1;
72  
73      /**
74       * List of ids retrieved from the ResultSet returned
75       * from the eFaps database. It represent one row in a result set.
76       */
77      private final List<Long> idList = new ArrayList<Long>();
78  
79      /**
80       * List of typeIds retrieved from the ResultSet returned
81       * from the eFaps database. It represent one row in a result set.
82       */
83      private final List<Long> typeIdList = new ArrayList<Long>();
84  
85      /**
86       * Iterator for the ids.
87       */
88      private Iterator<Long> idIterator;
89  
90      /**
91       * Iterator for the ypeIds.
92       */
93      private Iterator<Long> typeIdIterator;
94  
95      /**
96       * The instance this Select is linked to.
97       */
98      private Instance currentInstance;
99  
100     /**
101      * @param _attrName attribute name
102      * @param _type     type
103      */
104     public LinkToSelectPart(final String _attrName,
105                             final Type _type)
106     {
107         this.attrName = _attrName;
108         this.type = _type;
109     }
110 
111     /**
112      * {@inheritDoc}
113      */
114     @Override
115     public int join(final OneSelect _oneSelect,
116                     final SQLSelect _select,
117                     final int _relIndex)
118         throws EFapsException
119     {
120         // it must be evaluated if the attribute that is used as the base for the linkto is inside a child table
121         final Attribute attr = this.type.getAttribute(this.attrName);
122         if (attr == null) {
123             LinkToSelectPart.LOG.error("Could not find an Attribute with name '{}' for type:{}", this.attrName,
124                             this.type);
125             throw new EFapsException(LinkToSelectPart.class, "joinNoAttribute");
126         }
127         Integer relIndex = _relIndex;
128         if (attr != null && !attr.getTable().equals(this.type.getMainTable())) {
129             final String childTableName = attr.getTable().getSqlTable();
130             relIndex = _oneSelect.getTableIndex(childTableName, "ID", _relIndex, null);
131             if (relIndex == null) {
132                 relIndex = _oneSelect.getNewTableIndex(childTableName, "ID", _relIndex, null);
133                 _select.leftJoin(childTableName, relIndex, "ID", _relIndex, "ID");
134             }
135         }
136         Integer ret;
137         final String tableName = attr.getLink().getMainTable().getSqlTable();
138         final String column = attr.getSqlColNames().get(0);
139         ret = _oneSelect.getTableIndex(tableName, column, relIndex, null);
140         if (ret == null) {
141             ret = _oneSelect.getNewTableIndex(tableName, column, relIndex, null);
142             _select.leftJoin(tableName, ret, "ID", relIndex, column);
143         }
144         _select.column(ret, "ID");
145         this.idColumnIndex = _select.getColumns().size();
146         // select the type column if it has one
147         if (attr.getLink().getMainTable().getSqlColType() != null) {
148             _select.column(ret, attr.getLink().getMainTable().getSqlColType());
149             this.typeColumnIndex = _select.getColumns().size();
150         }
151         return ret;
152     }
153 
154     /**
155      * {@inheritDoc}
156      */
157     @Override
158     public Type getType()
159     {
160         final Attribute attr = this.type.getAttribute(this.attrName);
161         if (attr == null) {
162             LinkToSelectPart.LOG.error("Could not find an Attribute with name '{}' for type:{}", this.attrName,
163                             this.type);
164         }
165         Type ret = null;
166         try {
167             ret = attr.getLink();
168             if (ret == null) {
169                 LinkToSelectPart.LOG.error("No link for Attribute '{}'", attr);
170             }
171         } catch (final CacheReloadException e) {
172             LinkToSelectPart.LOG.error("Could not get Link for Attribute '{}'", attr);
173         }
174         return ret;
175     }
176 
177     /**
178      * {@inheritDoc}
179      */
180     @Override
181     public void addObject(final Object[] _row)
182         throws SQLException
183     {
184         this.idList.add((Long) _row[this.idColumnIndex - 1]);
185         if (this.typeColumnIndex > -1) {
186             this.typeIdList.add((Long) _row[this.typeColumnIndex - 1]);
187         }
188     }
189 
190     /**
191      * {@inheritDoc}
192      */
193     @Override
194     public Object getObject()
195     {
196         return this.idList;
197     }
198 
199     /**
200      * {@inheritDoc}
201      */
202     @Override
203     public void next()
204         throws EFapsException
205     {
206         if (this.typeIdIterator == null) {
207             this.typeIdIterator = this.typeIdList.iterator();
208         }
209         if (this.idIterator == null) {
210             this.idIterator = this.idList.iterator();
211         }
212         if (this.idIterator.hasNext()) {
213             final Long idTmp = this.idIterator.next();
214             if (idTmp == null) {
215                 this.currentInstance = Instance.get("");
216             } else {
217                 if (this.typeIdList.isEmpty()) {
218                     this.currentInstance = Instance.get(this.type.getAttribute(this.attrName).getLink(), idTmp);
219                 } else {
220                     final Long typeIdTmp = this.typeIdIterator.next();
221                     if (typeIdTmp != null) {
222                         this.currentInstance = Instance.get(Type.get(typeIdTmp), idTmp);
223                     }
224                 }
225             }
226         }
227     }
228 
229     /**
230      * Getter method for the instance variable {@link #currentInstance}.
231      *
232      * @return value of instance variable {@link #currentInstance}
233      */
234     public Instance getCurrentInstance()
235     {
236         return this.currentInstance;
237     }
238 }