1    /*
2     * Copyright 2009 :torweg free software group
3     *
4     * This program is free software: you can redistribute it and/or modify
5     * it under the terms of the GNU General Public License as published by
6     * the Free Software Foundation, either version 3 of the License, or
7     * (at your option) any later version.
8     * 
9     * This program is distributed in the hope that it will be useful,
10    * but WITHOUT ANY WARRANTY; without even the implied warranty of
11    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    * GNU General Public License for more details.
13    * 
14    * You should have received a copy of the GNU General Public License
15    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16    *
17    */
18   package org.torweg.pulse.component.statistics.model.aggregation;
19   
20   import java.util.HashSet;
21   import java.util.Set;
22   
23   import javax.persistence.Basic;
24   import javax.persistence.CascadeType;
25   import javax.persistence.ManyToOne;
26   import javax.persistence.MappedSuperclass;
27   import javax.persistence.OneToMany;
28   import javax.xml.bind.annotation.XmlAccessOrder;
29   import javax.xml.bind.annotation.XmlAccessType;
30   import javax.xml.bind.annotation.XmlAccessorOrder;
31   import javax.xml.bind.annotation.XmlAccessorType;
32   import javax.xml.bind.annotation.XmlElement;
33   import javax.xml.bind.annotation.XmlElementWrapper;
34   import javax.xml.bind.annotation.XmlRootElement;
35   import javax.xml.bind.annotation.XmlTransient;
36   
37   import org.hibernate.LazyInitializationException;
38   import org.torweg.pulse.util.entity.AbstractBasicEntity;
39   
40   /**
41    * An abstract base class to derive the actual aggregation for an {@code
42    * AbstractRegexVersioned} from.
43    * 
44    * @param <T>
45    *            the
46    *            {@code org.torweg.pulse.component.statistics.AbstractRegexVersioned}
47    *            being counted
48    * @param <U>
49    *            the underlying {@code AbstractRegexVersionedCounter}
50    * 
51    * @author Daniel Dietz
52    * @version $Revision: 1594 $
53    * 
54    */
55   @XmlRootElement(name = "abstract-regex-versioned-counter-aggregation")
56   @XmlAccessorOrder(XmlAccessOrder.UNDEFINED)
57   @XmlAccessorType(XmlAccessType.FIELD)
58   @MappedSuperclass
59   public abstract class AbstractRegexVersionedCounterAggregation<T, U extends AbstractRegexVersionedCounter<?>>
60           extends AbstractAggregation implements ICount {
61   
62       /**
63        * The serialVersionUID.
64        */
65       private static final long serialVersionUID = 3041219383267733481L;
66   
67       /**
68        * The underlying {@code
69        * org.torweg.pulse.component.statistics.AbstractRegexVersioned} being
70        * counted.
71        */
72       @ManyToOne(optional = false, cascade = { CascadeType.REFRESH,
73               CascadeType.MERGE, CascadeType.PERSIST })
74       @XmlTransient
75       // getter JAXB-annotated
76       private T counted;
77   
78       /**
79        * The {@code AbstractRegexVersionedCounter}s the {@code
80        * AbstractRegexVersionedCounterAggregation} operates on.
81        */
82       @OneToMany(cascade = CascadeType.ALL)
83       @XmlTransient
84       // getCountedIdJAXB JAXB-annotated
85       private final Set<U> counters = new HashSet<U>();
86   
87       /**
88        * The counter counter of the {@code
89        * AbstractRegexVersionedCounterAggregation}.
90        */
91       @Basic
92       @XmlElement(name = "counter")
93       private int counter;
94   
95       /**
96        * Returns the underlying {@code org.torweg.pulse.component.statistics.*}
97        * being counted.
98        * 
99        * @return &lt;T&gt;, the underlying {@code
100       *         org.torweg.pulse.component.statistics.*} being counted
101       */
102      @XmlTransient
103      public final T getCounted() {
104          return this.counted;
105      }
106  
107      /**
108       * For JAXB only.
109       * 
110       * @return this.getCounted().getId()
111       */
112      @XmlElement(name = "counted-id")
113      @SuppressWarnings("unused")
114      @Deprecated
115      private Long getCountedIdJAXB() {
116          try {
117              return ((AbstractBasicEntity) getCounted()).getId();
118          } catch (LazyInitializationException e) {
119              LOGGER.debug("igonred: " + e.getLocalizedMessage(), e);
120              return null;
121          }
122      }
123  
124      /**
125       * Sets the underlying {@code org.torweg.pulse.component.statistics.*} being
126       * counted.
127       * 
128       * @param count
129       *            the {@code org.torweg.pulse.component.statistics.*} to count
130       * 
131       * @throws NullPointerException
132       *             if the given count is {@code null}
133       */
134      protected final void setCounted(final T count) {
135          if (count == null) {
136              throw new NullPointerException("Given count must not be null.");
137          }
138          this.counted = count;
139      }
140  
141      /**
142       * Returns the underlying set of {@code AbstractRegexVersionedCounter}.
143       * 
144       * @return the <tt>counters</tt>
145       */
146      @XmlTransient
147      public final Set<U> getVersionCounters() {
148          return this.counters;
149      }
150  
151      /**
152       * * For JAXB only.
153       * 
154       * @return this.getVersionCounters()
155       */
156      @XmlElementWrapper(name = "version-counters")
157      @XmlElement(name = "version-counter")
158      @SuppressWarnings("unused")
159      @Deprecated
160      private Set<U> getVersionCountersJAXB() { // NOPMD
161          try {
162              return getVersionCounters();
163          } catch (LazyInitializationException e) {
164              LOGGER.debug("ignored: {}", e.getLocalizedMessage());
165              return null;
166          }
167      }
168  
169      /**
170       * Returns the counter.
171       * 
172       * @return the <tt>counter</tt>
173       */
174      public final int getCount() {
175          return this.counter;
176      }
177  
178      /**
179       * Sets the internal counter to the given value.
180       * 
181       * @param value
182       *            the value to set
183       * 
184       * @throws IllegalArgumentException
185       *             if
186       *             <ul>
187       *             <li>value &lt; 0</li>
188       *             </ul>
189       */
190      protected final void setCount(final int value) {
191          if (value < 0) {
192              throw new IllegalArgumentException("Given value must not be < 0.");
193          }
194          this.counter = value;
195      }
196  
197      /**
198       * Adds 1 to the internal counter counter.
199       */
200      protected final void increase() {
201          this.counter++;
202      }
203  
204      /**
205       * Returns the counter of unmatched {@code Visit}s.
206       * 
207       * @return the <tt>counter</tt> of unmatched {@code Visit}s
208       */
209      public final int getUnknownVersionTotal() {
210          int i = getCount();
211          for (U versionCounter : getVersionCounters()) {
212              i -= versionCounter.getCount();
213          }
214          return i;
215      }
216  
217      /**
218       * Returns a string representation.
219       * 
220       * @return a string representation
221       */
222      @Override
223      public String toString() {
224          return "{" + super.toString() + ", counter: " + getCount()
225                  + ", counted: " + getCounted().getClass().getCanonicalName()
226                  + "}";
227      }
228  
229  }
230