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.admin.user;
22  
23  import java.sql.PreparedStatement;
24  import java.sql.ResultSet;
25  import java.sql.SQLException;
26  import java.util.ArrayList;
27  import java.util.Collections;
28  import java.util.HashSet;
29  import java.util.List;
30  import java.util.Set;
31  import java.util.UUID;
32  import java.util.concurrent.TimeUnit;
33  
34  import org.efaps.db.Context;
35  import org.efaps.db.transaction.ConnectionResource;
36  import org.efaps.db.wrapper.SQLPart;
37  import org.efaps.db.wrapper.SQLSelect;
38  import org.efaps.util.EFapsException;
39  import org.efaps.util.cache.CacheLogListener;
40  import org.efaps.util.cache.CacheReloadException;
41  import org.efaps.util.cache.InfinispanCache;
42  import org.infinispan.Cache;
43  import org.slf4j.Logger;
44  import org.slf4j.LoggerFactory;
45  
46  /**
47   * TODO comment!
48   *
49   * @author The eFaps Team
50   * @version $Id$
51   */
52  public final class Consortium
53      extends AbstractUserObject
54  {
55  
56      /**
57       * Needed for serialization.
58       */
59      private static final long serialVersionUID = 1L;
60  
61      /**
62       * Logging instance used in this class.
63       */
64      private static final Logger LOG = LoggerFactory.getLogger(Consortium.class);
65  
66      /**
67       * This is the sql select statement to select all consortium 2 company
68       * relations from the database.
69       */
70      private static final String SQL_SELECTREL = new SQLSelect()
71                      .column("USERABSTRACTTO")
72                      .from("V_CONSORTIUM2COMPANY")
73                      .addPart(SQLPart.WHERE).addColumnPart(0, "ID").addPart(SQLPart.EQUAL).addValuePart("?").toString();
74  
75      /**
76       * This is the SQL select statement to select a Consortium from the database
77       * by ID.
78       */
79      private static final String SQL_ID = new SQLSelect().column("ID")
80                      .column("UUID")
81                      .column("NAME")
82                      .column("STATUS")
83                      .from("V_USERCONSORTIUM", 0)
84                      .addPart(SQLPart.WHERE).addColumnPart(0, "ID").addPart(SQLPart.EQUAL).addValuePart("?").toString();
85  
86      /**
87       * This is the SQL select statement to select a role from the database by
88       * Name.
89       */
90      private static final String SQL_NAME = new SQLSelect().column("ID")
91                      .column("UUID")
92                      .column("NAME")
93                      .column("STATUS")
94                      .from("V_USERCONSORTIUM", 0)
95                      .addPart(SQLPart.WHERE).addColumnPart(0, "NAME").addPart(SQLPart.EQUAL).addValuePart("?")
96                      .toString();
97  
98      /**
99       * This is the SQL select statement to select a role from the database by
100      * UUID.
101      */
102     private static final String SQL_UUID = new SQLSelect().column("ID")
103                     .column("UUID")
104                     .column("NAME")
105                     .column("STATUS")
106                     .from("V_USERCONSORTIUM", 0)
107                     .addPart(SQLPart.WHERE).addColumnPart(0, "UUID").addPart(SQLPart.EQUAL).addValuePart("?")
108                     .toString();
109 
110     /**
111      * Name of the Cache by UUID.
112      */
113     private static final String UUIDCACHE = Consortium.class.getName() + ".UUID";
114 
115     /**
116      * Name of the Cache by ID.
117      */
118     private static final String IDCACHE = Consortium.class.getName() + ".ID";
119 
120     /**
121      * Name of the Cache by Name.
122      */
123     private static final String NAMECACHE = Consortium.class.getName() + ".Name";
124 
125     /**
126      * Use to mark not found and return <code>null</code>.
127      */
128     private static final Consortium NULL = new Consortium(0, null, null, false);
129 
130     /**
131      * The companies belonging to this Consortium.
132      */
133     private final Set<Long> companieIds = new HashSet<Long>();
134 
135     /**
136      * @param _id id for this company
137      * @param _uuid uuid for this company
138      * @param _name name for this company
139      * @param _status status for this company
140      */
141     private Consortium(final long _id,
142                        final String _uuid,
143                        final String _name,
144                        final boolean _status)
145     {
146         super(_id, _uuid, _name, _status);
147     }
148 
149     /**
150      * @param _companyId ID of the Company to add to this Consortium
151      */
152     protected void addCompany(final Long _companyId)
153     {
154         this.companieIds.add(_companyId);
155     }
156 
157     /**
158      * Get the related Companies (unmodifiable).
159      *
160      * @return the set of related Companies
161      */
162     public Set<Long> getCompanies()
163     {
164         return Collections.unmodifiableSet(this.companieIds);
165     }
166 
167     /**
168      * {@inheritDoc}
169      */
170     @Override
171     public boolean isAssigned()
172     {
173         boolean ret = false;
174         try {
175             if (Context.getThreadContext().getCompany() != null) {
176                 if (Context.getThreadContext().getCompany().getId() == getId()) {
177                     ret = hasChildPerson(Context.getThreadContext().getPerson());
178                 }
179             } else {
180                 ret = true;
181             }
182         } catch (final EFapsException e) {
183             Consortium.LOG.error("could not read Company or Person from Context ", e);
184         }
185         return ret;
186     }
187 
188     /*
189      * (non-Javadoc)
190      * @see
191      * org.efaps.admin.user.AbstractUserObject#hasChildPerson(org.efaps.admin
192      * .user.Person)
193      */
194     @Override
195     public boolean hasChildPerson(final Person _person)
196     {
197         // TODO Auto-generated method stub
198         return false;
199     }
200 
201     /**
202      * Method to initialize the Cache of this CacheObjectInterface.
203      */
204     public static void initialize()
205     {
206         if (InfinispanCache.get().exists(Consortium.UUIDCACHE)) {
207             InfinispanCache.get().<UUID, Consortium>getCache(Consortium.UUIDCACHE).clear();
208         } else {
209             InfinispanCache.get().<UUID, Consortium>getCache(Consortium.UUIDCACHE)
210                             .addListener(new CacheLogListener(Consortium.LOG));
211         }
212         if (InfinispanCache.get().exists(Consortium.IDCACHE)) {
213             InfinispanCache.get().<Long, Consortium>getCache(Consortium.IDCACHE).clear();
214         } else {
215             InfinispanCache.get().<Long, Consortium>getCache(Consortium.IDCACHE)
216                             .addListener(new CacheLogListener(Consortium.LOG));
217         }
218         if (InfinispanCache.get().exists(Consortium.NAMECACHE)) {
219             InfinispanCache.get().<String, Consortium>getCache(Consortium.NAMECACHE).clear();
220         } else {
221             InfinispanCache.get().<String, Consortium>getCache(Consortium.NAMECACHE)
222                             .addListener(new CacheLogListener(Consortium.LOG));
223         }
224     }
225 
226     /**
227      * Returns for given parameter <i>_id</i> the instance of class
228      * {@link Consortium}.
229      *
230      * @param _id id to search in the cache
231      * @return instance of class {@link Consortium}
232      * @throws CacheReloadException on error
233      * @see #getCache
234      */
235     public static Consortium get(final long _id)
236         throws CacheReloadException
237     {
238         final Cache<Long, Consortium> cache = InfinispanCache.get().<Long, Consortium>getCache(Consortium.IDCACHE);
239         if (!cache.containsKey(_id) && !Consortium.getConsortiumFromDB(Consortium.SQL_ID, _id)) {
240             cache.put(_id, Consortium.NULL, 100, TimeUnit.SECONDS);
241         }
242         final Consortium ret = cache.get(_id);
243         return ret.equals(Consortium.NULL) ? null : ret;
244     }
245 
246     /**
247      * Returns for given parameter <i>_name</i> the instance of class
248      * {@link Consortium}.
249      *
250      * @param _name name to search in the cache
251      * @return instance of class {@link Consortium}
252      * @throws CacheReloadException on error
253      * @see #getCache
254      */
255     public static Consortium get(final String _name)
256         throws CacheReloadException
257     {
258         final Cache<String, Consortium> cache = InfinispanCache.get().<String, Consortium>getCache(Consortium.IDCACHE);
259         if (!cache.containsKey(_name) && !Consortium.getConsortiumFromDB(Consortium.SQL_NAME, _name)) {
260             cache.put(_name, Consortium.NULL, 100, TimeUnit.SECONDS);
261         }
262         final Consortium ret = cache.get(_name);
263         return ret.equals(Consortium.NULL) ? null : ret;
264     }
265 
266     /**
267      * Returns for given parameter <i>_uuid</i> the instance of class
268      * {@link Consortium}.
269      *
270      * @param _uuid UUI to search for
271      * @return instance of class {@link Consortium}
272      * @throws CacheReloadException on error
273      */
274     public static Consortium get(final UUID _uuid)
275         throws CacheReloadException
276     {
277         final Cache<UUID, Consortium> cache = InfinispanCache.get().<UUID, Consortium>getCache(Consortium.IDCACHE);
278         if (!cache.containsKey(_uuid)) {
279             Consortium.getConsortiumFromDB(Consortium.SQL_UUID, String.valueOf(_uuid));
280         }
281         return cache.get(_uuid);
282     }
283 
284     /**
285      * @param _consortium Consortium to be cached
286      */
287     private static void cacheConsortium(final Consortium _consortium)
288     {
289         final Cache<UUID, Consortium> cache4UUID = InfinispanCache.get().<UUID, Consortium>getIgnReCache(
290                         Consortium.UUIDCACHE);
291         cache4UUID.putIfAbsent(_consortium.getUUID(), _consortium);
292 
293         final Cache<String, Consortium> nameCache = InfinispanCache.get().<String, Consortium>getIgnReCache(
294                         Consortium.NAMECACHE);
295         nameCache.put(_consortium.getName(), _consortium);
296 
297         final Cache<Long, Consortium> idCache = InfinispanCache.get().<Long, Consortium>getIgnReCache(
298                         Consortium.IDCACHE);
299         idCache.put(_consortium.getId(), _consortium);
300     }
301 
302     /**
303      * @param _sql SQL Statment to be execuetd
304      * @param _criteria filter criteria
305      * @return true if successful
306      * @throws CacheReloadException on error
307      */
308     private static boolean getConsortiumFromDB(final String _sql,
309                                                final Object _criteria)
310         throws CacheReloadException
311     {
312         boolean ret = false;
313         ConnectionResource con = null;
314         try {
315             Consortium consortium = null;
316             con = Context.getThreadContext().getConnectionResource();
317             PreparedStatement stmt = null;
318             try {
319                 stmt = con.getConnection().prepareStatement(_sql);
320                 stmt.setObject(1, _criteria);
321                 final ResultSet rs = stmt.executeQuery();
322 
323                 if (rs.next()) {
324                     final long id = rs.getLong(1);
325                     final String uuid = rs.getString(2);
326                     final String name = rs.getString(3).trim();
327                     final boolean status = rs.getBoolean(4);
328                     Consortium.LOG.debug("read consortium '" + name + "' (id = " + id + ")");
329                     consortium = new Consortium(id, uuid, name, status);
330                 }
331                 rs.close();
332             } finally {
333                 if (stmt != null) {
334                     stmt.close();
335                 }
336             }
337             con.commit();
338             if (consortium != null) {
339                 ret = true;
340                 Consortium.cacheConsortium(consortium);
341                 consortium.getCompanyRelationFromDB();
342             }
343         } catch (final SQLException e) {
344             throw new CacheReloadException("could not read consortiums", e);
345         } catch (final EFapsException e) {
346             throw new CacheReloadException("could not read consortiums", e);
347         } finally {
348             if ((con != null) && con.isOpened()) {
349                 try {
350                     con.abort();
351                 } catch (final EFapsException e) {
352                     throw new CacheReloadException("could not read consortiums", e);
353                 }
354             }
355         }
356         return ret;
357     }
358 
359     /**
360      * @throws CacheReloadException on error
361      */
362     private void getCompanyRelationFromDB()
363         throws CacheReloadException
364     {
365         ConnectionResource con = null;
366         try {
367             final List<Long> companyIds = new ArrayList<Long>();
368             con = Context.getThreadContext().getConnectionResource();
369             PreparedStatement stmt = null;
370             try {
371                 stmt = con.getConnection().prepareStatement(Consortium.SQL_SELECTREL);
372                 stmt.setObject(1, getId());
373                 final ResultSet rs = stmt.executeQuery();
374 
375                 while (rs.next()) {
376                     companyIds.add(rs.getLong(1));
377                 }
378                 rs.close();
379 
380             } finally {
381                 if (stmt != null) {
382                     stmt.close();
383                 }
384             }
385             con.commit();
386             for (final Long companyId : companyIds) {
387                 final Company company = Company.get(companyId);
388                 Consortium.LOG.debug("read consortium 2 company relation '{} - {}'",
389                                 new Object[] { getName(), company.getName() });
390                 if (company != null) {
391                     addCompany(company.getId());
392                     company.addConsortium(getId());
393                 }
394             }
395         } catch (final SQLException e) {
396             throw new CacheReloadException("could not read consortiums", e);
397         } catch (final EFapsException e) {
398             throw new CacheReloadException("could not read consortiums", e);
399         } finally {
400             if ((con != null) && con.isOpened()) {
401                 try {
402                     con.abort();
403                 } catch (final EFapsException e) {
404                     throw new CacheReloadException("could not read consortiums", e);
405                 }
406             }
407         }
408     }
409 
410     @Override
411     public boolean equals(final Object _obj)
412     {
413         boolean ret;
414         if (_obj instanceof Consortium) {
415             ret = ((Consortium) _obj).getId() == getId();
416         } else {
417             ret = super.equals(_obj);
418         }
419         return ret;
420     }
421 
422     @Override
423     public int hashCode()
424     {
425         return  Long.valueOf(getId()).intValue();
426     }
427 
428 }