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 javax.persistence.Basic;
21   import javax.persistence.Column;
22   import javax.persistence.ManyToOne;
23   import javax.persistence.MappedSuperclass;
24   import javax.xml.bind.annotation.XmlAccessOrder;
25   import javax.xml.bind.annotation.XmlAccessType;
26   import javax.xml.bind.annotation.XmlAccessorOrder;
27   import javax.xml.bind.annotation.XmlAccessorType;
28   import javax.xml.bind.annotation.XmlElement;
29   import javax.xml.bind.annotation.XmlRootElement;
30   import javax.xml.bind.annotation.XmlTransient;
31   
32   import org.hibernate.LazyInitializationException;
33   import org.slf4j.Logger;
34   import org.slf4j.LoggerFactory;
35   import org.torweg.pulse.component.statistics.model.StatisticsServer;
36   import org.torweg.pulse.util.entity.Node;
37   
38   /**
39    * An abstract base class to derive the nodes the {@code
40    * AbstractTreeAggregation} operates on from.
41    * 
42    * @param <T>
43    *            the actual implementation of the {@code AbstractTreeElement}
44    * 
45    * @author Daniel Dietz
46    * @version $Revision: 1579 $
47    */
48   @XmlRootElement(name = "abstract-tree-element")
49   @XmlAccessorOrder(XmlAccessOrder.UNDEFINED)
50   @XmlAccessorType(XmlAccessType.FIELD)
51   @MappedSuperclass
52   public abstract class AbstractTreeElement<T extends AbstractTreeElement<T>>
53           extends Node {
54   
55       /**
56        * The serialVersionUID.
57        */
58       private static final long serialVersionUID = 2517625678832756338L;
59   
60       /**
61        * The logger.
62        */
63       protected static final Logger LOGGER = LoggerFactory
64               .getLogger(AbstractTreeElement.class);
65   
66       /**
67        * The name of the pathString element represented by this {@code
68        * AbstractTreeElement}.
69        */
70       @Basic
71       @Column(nullable = false)
72       @XmlElement(name = "path-string")
73       private String pathString;
74   
75       /**
76        * Indicates a root-{@code AbstractTreeElement}.
77        */
78       @Basic(optional = false)
79       @XmlElement(name = "root-node")
80       private boolean rootNode = false;
81   
82       /**
83        * the server the path element belongs to.
84        */
85       @ManyToOne(optional = false)
86       @XmlTransient
87       private StatisticsServer server;
88   
89       /**
90        * Sets the {@code StatisticsServer}.
91        * 
92        * @param s
93        *            the {@code StatisticsServer}
94        */
95       protected void setServer(final StatisticsServer s) {
96           if (s == null) {
97               throw new NullPointerException("Given server must not be null.");
98           }
99           this.server = s;
100      }
101  
102      /**
103       * returns the statistics server the path element belongs to.
104       * 
105       * @return the statistics server the path element belongs to
106       */
107      @XmlTransient
108      public final StatisticsServer getStatisticsServer() {
109          return this.server;
110      }
111  
112      /**
113       * For JAXB only.
114       * 
115       * @return this.getStatisticsServer()
116       */
117      @XmlElement(name = "statistics-server")
118      @SuppressWarnings("unused")
119      @Deprecated
120      private StatisticsServer getStatisticsServerJAXB() { // NOPMD
121          try {
122              return getStatisticsServer();
123          } catch (LazyInitializationException e) {
124              LOGGER.debug("ignored: {}", e.getLocalizedMessage());
125              return null;
126          }
127      }
128  
129      /**
130       * Indicates whether the current {@code AbstractTreeElement} is a root-
131       * {@code AbstractTreeElement}.
132       * 
133       * @return the <tt>rootNode</tt>: {@code true} if and only if the current
134       *         {@code AbstractTreeElement} is a root- {@code
135       *         AbstractTreeElement}, {@code false} otherwise
136       */
137      public final boolean isRootNode() {
138          return this.rootNode;
139      }
140  
141      /**
142       * Sets the <tt>rootNode</tt> for the {@code AbstractTreeElement}.
143       * 
144       * @param isRootNode
145       *            {@code true} to mark the {@code AbstractTreeElement} as root
146       *            node, {@code false} otherwise
147       */
148      protected final void setRooNode(final boolean isRootNode) {
149          this.rootNode = isRootNode;
150      }
151  
152      /**
153       * Returns the pathString as represented by this {@code AbstractTreeElement}
154       * .
155       * 
156       * @return the pathString
157       */
158      public final String getPathString() {
159          if (this.pathString.length() == 0) {
160              return getStatisticsServer().getHostName();
161          }
162          return this.pathString;
163      }
164  
165      /**
166       * Returns the pathString as represented by this {@code AbstractTreeElement}
167       * .
168       * 
169       * @param pString
170       *            the pathString to set
171       * 
172       * @throws NullPointerException
173       *             if the pString is {@code null}
174       * @throws IllegalArgumentException
175       *             if the pString is an empty string or contains
176       *             whitespace-characters only
177       */
178      protected final void setPathString(final String pString) {
179          if (pString == null) {
180              throw new NullPointerException(
181                      "The given pathString must not be null.");
182          }
183          String trimmed = pString.trim();
184          if (trimmed.length() == 0) {
185              throw new IllegalArgumentException(
186                      "The pathString must contain at least "
187                              + "one non-whitespace character.");
188          }
189          this.pathString = trimmed;
190      }
191  
192      /**
193       * Sets the pathString to empty string.
194       * 
195       * @param statisticsServer
196       *            a {@code StatisticsServer}
197       * 
198       * @throws NullPointerException
199       *             if the statisticsServer is {@code null}
200       */
201      protected final void setPathString(final StatisticsServer statisticsServer) {
202          if (statisticsServer == null) {
203              throw new NullPointerException(
204                      "The given statisticsServer must not be null.");
205          }
206          this.pathString = "";
207      }
208  
209      /**
210       * Returns a child of the {@code Node} by given path.
211       * 
212       * @param path
213       *            the name of the path element
214       * @return the {@code Node} or {@code null} if not child for the given path
215       *         exists
216       */
217      @SuppressWarnings("unchecked")
218      public final T getChildByPathString(final String path) {
219          for (Node n : getChildren()) {
220              if (((T) n).getPathString().equals(path.trim())) {
221                  return (T) n;
222              }
223          }
224          return null;
225      }
226  
227      /**
228       * @return string representation of the {@code PathTreeAggregation}
229       */
230      @Override
231      public final String toString() {
232          return "{" + super.toString() + "@[" + getId() + "], pathString: "
233                  + getPathString() + ", server: " + getStatisticsServer() + "}";
234      }
235  
236  }
237