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  package org.efaps.db;
22  
23  import java.util.ArrayList;
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Map.Entry;
30  import java.util.Set;
31  
32  import org.efaps.admin.access.AccessTypeEnums;
33  import org.efaps.admin.datamodel.Type;
34  import org.efaps.db.print.OneSelect;
35  import org.efaps.util.EFapsException;
36  
37  /**
38   *
39   *
40   * @author The eFaps Team
41   * @version $Id$
42   */
43  public class MultiPrintQuery
44      extends AbstractPrintQuery
45  {
46  
47      /**
48       * Instances this PrintQuery is based on.
49       */
50      private final List<Instance> instances;
51  
52      /**
53       * Main type of this Query.
54       */
55      private final Type mainType;
56  
57      /**
58       * Iterator used to iterate over the given instances.
59       */
60      private Iterator<Instance> iterator;
61  
62      /**
63       * Current instance.
64       */
65      private Instance current;
66  
67      /**
68       * @param _instances instance to be updated.
69       * @throws EFapsException on error
70       */
71      public MultiPrintQuery(final List<Instance> _instances)
72          throws EFapsException
73      {
74          this.instances = _instances;
75          if (this.instances.size() > 0) {
76              final Set<Type> types = new HashSet<Type>();
77              for (final Instance instance : _instances) {
78                  if (!types.contains(instance.getType())) {
79                      types.add(instance.getType());
80                  }
81              }
82              // if only one type is given the main type is this type
83              // if more than one type is given they must have the same parent
84              // type, if not it will not work. The next common parent is used.
85              if (types.size() == 1) {
86                  this.mainType = _instances.get(0).getType();
87              } else {
88                  final List<List<Type>> typeLists = new ArrayList<List<Type>>();
89                  for (final Type type : types) {
90                      final List<Type> parents = new ArrayList<Type>();
91                      Type currentType = type;
92                      parents.add(currentType);
93                      while (currentType.getParentType() != null) {
94                          currentType = currentType.getParentType();
95                          parents.add(currentType);
96                      }
97                      typeLists.add(parents);
98                  }
99  
100                 Type tempType = null;
101                 final List<Type> compList = typeLists.get(0);
102                 typeLists.remove(0);
103                 for (final Type comp : compList) {
104                     boolean found = true;
105                     for (final List<Type> typeList : typeLists) {
106                         if (!typeList.contains(comp)) {
107                             found = false;
108                             break;
109                         }
110                     }
111                     if (found) {
112                         tempType = comp;
113                         break;
114                     }
115                 }
116                 this.mainType = tempType;
117             }
118         } else {
119             this.mainType = null;
120         }
121     }
122 
123     /**
124      * {@inheritDoc}
125      */
126     @Override
127     public Type getMainType()
128     {
129         return this.mainType;
130     }
131 
132     /**
133      * {@inheritDoc}
134      */
135     @Override
136     public Instance getCurrentInstance()
137     {
138         return this.current;
139     }
140 
141     /**
142      * {@inheritDoc}
143      */
144     @Override
145     public List<Instance> getInstanceList()
146     {
147         return this.instances;
148     }
149 
150     /**
151      * {@inheritDoc}
152      */
153     @Override
154     public boolean execute()
155         throws EFapsException
156     {
157         if (isMarked4execute()) {
158             final Map<Type, List<Instance>> types = new HashMap<Type, List<Instance>>();
159             for (final Instance instance : this.instances) {
160                 List<Instance> list;
161                 if (!types.containsKey(instance.getType())) {
162                     list = new ArrayList<Instance>();
163                     types.put(instance.getType(), list);
164                 } else {
165                     list = types.get(instance.getType());
166                 }
167                 list.add(instance);
168             }
169             // check the access for the given instances
170             final Map<Instance, Boolean> accessmap = new HashMap<Instance, Boolean>();
171             for (final Entry<Type, List<Instance>> entry : types.entrySet()) {
172                 accessmap.putAll(entry.getKey().checkAccess(entry.getValue(), AccessTypeEnums.READ.getAccessType()));
173             }
174 
175             final Iterator<Instance> tempIter = this.instances.iterator();
176             while (tempIter.hasNext()) {
177                 final Instance instance = tempIter.next();
178                 if (accessmap.size() > 0) {
179                     if (!accessmap.containsKey(instance) || !accessmap.get(instance)) {
180                         tempIter.remove();
181                     }
182                 }
183             }
184         }
185         return executeWithoutAccessCheck();
186     }
187 
188     /**
189      * Method to move the iterator to the next value.
190      *
191      * @return true if the iterator was moved successfully to the next value
192      * @throws EFapsException on error
193      */
194     public boolean next()
195         throws EFapsException
196     {
197         boolean ret = false;
198         if (this.iterator == null) {
199             this.iterator = this.instances.iterator();
200         }
201         if (this.iterator.hasNext()) {
202             this.current = this.iterator.next();
203             ret = true;
204         }
205         if (ret) {
206             for (final OneSelect oneSelect : getAllSelects()) {
207                 ret = oneSelect.next();
208                 if (!ret) {
209                     break;
210                 }
211             }
212         }
213         return ret;
214     }
215 
216     /**
217      * {@inheritDoc}
218      */
219     @Override
220     public boolean isCacheEnabled()
221     {
222         return false;
223     }
224 }