View Javadoc

1   /*
2    * Copyright 2007-2013 smartics, Kronseder & Reiner GmbH
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  package de.smartics.exceptions.id;
17  
18  import java.util.concurrent.atomic.AtomicLong;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  
23  import de.smartics.exceptions.core.IdFactory;
24  
25  /**
26   * The factory that created {@link de.smartics.exceptions.core.ExceptionId}s
27   * that provides a number that is larger than zero. If the last number has been
28   * provided, it continues with 1, issuing a message on info level.
29   */
30  public class IncrementFactory implements IdFactory
31  {
32    // ********************************* Fields *********************************
33  
34    // --- constants ------------------------------------------------------------
35  
36    // --- members --------------------------------------------------------------
37  
38    /**
39     * Reference to the logger for this class.
40     */
41    private final Log log = LogFactory.getLog(IncrementFactory.class);
42  
43    /**
44     * The thread-safe incrementor of long values.
45     */
46    private final AtomicLong atomic;
47  
48    // ****************************** Initializer *******************************
49  
50    // ****************************** Constructors ******************************
51  
52    /**
53     * Default constructor with counter initialized with <code>1</code>.
54     */
55    public IncrementFactory()
56    {
57      this(1);
58    }
59  
60    /**
61     * Convenience constructor.
62     *
63     * @param startValue the start value of the counter.
64     * @throws IllegalArgumentException if the start value is smaller than or
65     *           equal to zero.
66     */
67    public IncrementFactory(final long startValue)
68      throws IllegalArgumentException
69    {
70      if (startValue <= 0L)
71      {
72        throw new IllegalArgumentException(
73            "Start value must be greater than zero, but is '" + startValue + "'.");
74      }
75      this.atomic = new AtomicLong(startValue);
76    }
77  
78    // ****************************** Inner Classes *****************************
79  
80    // ********************************* Methods ********************************
81  
82    // --- init -----------------------------------------------------------------
83  
84    // --- get&set --------------------------------------------------------------
85  
86    // --- business -------------------------------------------------------------
87  
88    @Override
89    public LongExceptionId createId()
90    {
91      boolean notSet;
92      long current;
93      do
94      {
95        current = atomic.getAndIncrement();
96        notSet = false;
97  
98        if (current <= 0L)
99        {
100         final boolean success = atomic.compareAndSet(current + 1, 2);
101         if (success)
102         {
103           current = 1;
104           if (log.isInfoEnabled())
105           {
106             log.info("Increment factory resetted exception identifier to '1'.");
107           }
108         }
109         else
110         {
111           notSet = true;
112         }
113       }
114     }
115     while (notSet);
116 
117     return new LongExceptionId(current);
118   }
119 
120   // --- object basics --------------------------------------------------------
121 }