001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package org.apache.hadoop.yarn.api.records.timeline;
020    
021    import java.util.ArrayList;
022    import java.util.HashMap;
023    import java.util.HashSet;
024    import java.util.List;
025    import java.util.Map;
026    import java.util.Map.Entry;
027    import java.util.Set;
028    
029    import javax.xml.bind.annotation.XmlAccessType;
030    import javax.xml.bind.annotation.XmlAccessorType;
031    import javax.xml.bind.annotation.XmlElement;
032    import javax.xml.bind.annotation.XmlRootElement;
033    
034    import org.apache.hadoop.classification.InterfaceAudience.Public;
035    import org.apache.hadoop.classification.InterfaceStability.Unstable;
036    
037    /**
038     * <p>
039     * The class that contains the the meta information of some conceptual entity
040     * and its related events. The entity can be an application, an application
041     * attempt, a container or whatever the user-defined object.
042     * </p>
043     * 
044     * <p>
045     * Primary filters will be used to index the entities in
046     * <code>TimelineStore</code>, such that users should carefully choose the
047     * information they want to store as the primary filters. The remaining can be
048     * stored as other information.
049     * </p>
050     */
051    @XmlRootElement(name = "entity")
052    @XmlAccessorType(XmlAccessType.NONE)
053    @Public
054    @Unstable
055    public class TimelineEntity implements Comparable<TimelineEntity> {
056    
057      private String entityType;
058      private String entityId;
059      private Long startTime;
060      private List<TimelineEvent> events = new ArrayList<TimelineEvent>();
061      private Map<String, Set<String>> relatedEntities =
062          new HashMap<String, Set<String>>();
063      private Map<String, Set<Object>> primaryFilters =
064          new HashMap<String, Set<Object>>();
065      private Map<String, Object> otherInfo =
066          new HashMap<String, Object>();
067    
068      public TimelineEntity() {
069    
070      }
071    
072      /**
073       * Get the entity type
074       * 
075       * @return the entity type
076       */
077      @XmlElement(name = "entitytype")
078      public String getEntityType() {
079        return entityType;
080      }
081    
082      /**
083       * Set the entity type
084       * 
085       * @param entityType
086       *          the entity type
087       */
088      public void setEntityType(String entityType) {
089        this.entityType = entityType;
090      }
091    
092      /**
093       * Get the entity Id
094       * 
095       * @return the entity Id
096       */
097      @XmlElement(name = "entity")
098      public String getEntityId() {
099        return entityId;
100      }
101    
102      /**
103       * Set the entity Id
104       * 
105       * @param entityId
106       *          the entity Id
107       */
108      public void setEntityId(String entityId) {
109        this.entityId = entityId;
110      }
111    
112      /**
113       * Get the start time of the entity
114       * 
115       * @return the start time of the entity
116       */
117      @XmlElement(name = "starttime")
118      public Long getStartTime() {
119        return startTime;
120      }
121    
122      /**
123       * Set the start time of the entity
124       * 
125       * @param startTime
126       *          the start time of the entity
127       */
128      public void setStartTime(Long startTime) {
129        this.startTime = startTime;
130      }
131    
132      /**
133       * Get a list of events related to the entity
134       * 
135       * @return a list of events related to the entity
136       */
137      @XmlElement(name = "events")
138      public List<TimelineEvent> getEvents() {
139        return events;
140      }
141    
142      /**
143       * Add a single event related to the entity to the existing event list
144       * 
145       * @param event
146       *          a single event related to the entity
147       */
148      public void addEvent(TimelineEvent event) {
149        events.add(event);
150      }
151    
152      /**
153       * Add a list of events related to the entity to the existing event list
154       * 
155       * @param events
156       *          a list of events related to the entity
157       */
158      public void addEvents(List<TimelineEvent> events) {
159        this.events.addAll(events);
160      }
161    
162      /**
163       * Set the event list to the given list of events related to the entity
164       * 
165       * @param events
166       *          events a list of events related to the entity
167       */
168      public void setEvents(List<TimelineEvent> events) {
169        this.events = events;
170      }
171    
172      /**
173       * Get the related entities
174       * 
175       * @return the related entities
176       */
177      @XmlElement(name = "relatedentities")
178      public Map<String, Set<String>> getRelatedEntities() {
179        return relatedEntities;
180      }
181    
182      /**
183       * Add an entity to the existing related entity map
184       * 
185       * @param entityType
186       *          the entity type
187       * @param entityId
188       *          the entity Id
189       */
190      public void addRelatedEntity(String entityType, String entityId) {
191        Set<String> thisRelatedEntity = relatedEntities.get(entityType);
192        if (thisRelatedEntity == null) {
193          thisRelatedEntity = new HashSet<String>();
194          relatedEntities.put(entityType, thisRelatedEntity);
195        }
196        thisRelatedEntity.add(entityId);
197      }
198    
199      /**
200       * Add a map of related entities to the existing related entity map
201       * 
202       * @param relatedEntities
203       *          a map of related entities
204       */
205      public void addRelatedEntities(Map<String, Set<String>> relatedEntities) {
206        for (Entry<String, Set<String>> relatedEntity : relatedEntities.entrySet()) {
207          Set<String> thisRelatedEntity =
208              this.relatedEntities.get(relatedEntity.getKey());
209          if (thisRelatedEntity == null) {
210            this.relatedEntities.put(
211                relatedEntity.getKey(), relatedEntity.getValue());
212          } else {
213            thisRelatedEntity.addAll(relatedEntity.getValue());
214          }
215        }
216      }
217    
218      /**
219       * Set the related entity map to the given map of related entities
220       * 
221       * @param relatedEntities
222       *          a map of related entities
223       */
224      public void setRelatedEntities(
225          Map<String, Set<String>> relatedEntities) {
226        this.relatedEntities = relatedEntities;
227      }
228    
229      /**
230       * Get the primary filters
231       * 
232       * @return the primary filters
233       */
234      @XmlElement(name = "primaryfilters")
235      public Map<String, Set<Object>> getPrimaryFilters() {
236        return primaryFilters;
237      }
238    
239      /**
240       * Add a single piece of primary filter to the existing primary filter map
241       * 
242       * @param key
243       *          the primary filter key
244       * @param value
245       *          the primary filter value
246       */
247      public void addPrimaryFilter(String key, Object value) {
248        Set<Object> thisPrimaryFilter = primaryFilters.get(key);
249        if (thisPrimaryFilter == null) {
250          thisPrimaryFilter = new HashSet<Object>();
251          primaryFilters.put(key, thisPrimaryFilter);
252        }
253        thisPrimaryFilter.add(value);
254      }
255    
256      /**
257       * Add a map of primary filters to the existing primary filter map
258       * 
259       * @param primaryFilters
260       *          a map of primary filters
261       */
262      public void addPrimaryFilters(Map<String, Set<Object>> primaryFilters) {
263        for (Entry<String, Set<Object>> primaryFilter : primaryFilters.entrySet()) {
264          Set<Object> thisPrimaryFilter =
265              this.primaryFilters.get(primaryFilter.getKey());
266          if (thisPrimaryFilter == null) {
267            this.primaryFilters.put(
268                primaryFilter.getKey(), primaryFilter.getValue());
269          } else {
270            thisPrimaryFilter.addAll(primaryFilter.getValue());
271          }
272        }
273      }
274    
275      /**
276       * Set the primary filter map to the given map of primary filters
277       * 
278       * @param primaryFilters
279       *          a map of primary filters
280       */
281      public void setPrimaryFilters(Map<String, Set<Object>> primaryFilters) {
282        this.primaryFilters = primaryFilters;
283      }
284    
285      /**
286       * Get the other information of the entity
287       * 
288       * @return the other information of the entity
289       */
290      @XmlElement(name = "otherinfo")
291      public Map<String, Object> getOtherInfo() {
292        return otherInfo;
293      }
294    
295      /**
296       * Add one piece of other information of the entity to the existing other info
297       * map
298       * 
299       * @param key
300       *          the other information key
301       * @param value
302       *          the other information value
303       */
304      public void addOtherInfo(String key, Object value) {
305        this.otherInfo.put(key, value);
306      }
307    
308      /**
309       * Add a map of other information of the entity to the existing other info map
310       * 
311       * @param otherInfo
312       *          a map of other information
313       */
314      public void addOtherInfo(Map<String, Object> otherInfo) {
315        this.otherInfo.putAll(otherInfo);
316      }
317    
318      /**
319       * Set the other info map to the given map of other information
320       * 
321       * @param otherInfo
322       *          a map of other information
323       */
324      public void setOtherInfo(Map<String, Object> otherInfo) {
325        this.otherInfo = otherInfo;
326      }
327    
328      @Override
329      public int hashCode() {
330        // generated by eclipse
331        final int prime = 31;
332        int result = 1;
333        result = prime * result + ((entityId == null) ? 0 : entityId.hashCode());
334        result =
335            prime * result + ((entityType == null) ? 0 : entityType.hashCode());
336        result = prime * result + ((events == null) ? 0 : events.hashCode());
337        result = prime * result + ((otherInfo == null) ? 0 : otherInfo.hashCode());
338        result =
339            prime * result
340                + ((primaryFilters == null) ? 0 : primaryFilters.hashCode());
341        result =
342            prime * result
343                + ((relatedEntities == null) ? 0 : relatedEntities.hashCode());
344        result = prime * result + ((startTime == null) ? 0 : startTime.hashCode());
345        return result;
346      }
347    
348      @Override
349      public boolean equals(Object obj) {
350        // generated by eclipse
351        if (this == obj)
352          return true;
353        if (obj == null)
354          return false;
355        if (getClass() != obj.getClass())
356          return false;
357        TimelineEntity other = (TimelineEntity) obj;
358        if (entityId == null) {
359          if (other.entityId != null)
360            return false;
361        } else if (!entityId.equals(other.entityId))
362          return false;
363        if (entityType == null) {
364          if (other.entityType != null)
365            return false;
366        } else if (!entityType.equals(other.entityType))
367          return false;
368        if (events == null) {
369          if (other.events != null)
370            return false;
371        } else if (!events.equals(other.events))
372          return false;
373        if (otherInfo == null) {
374          if (other.otherInfo != null)
375            return false;
376        } else if (!otherInfo.equals(other.otherInfo))
377          return false;
378        if (primaryFilters == null) {
379          if (other.primaryFilters != null)
380            return false;
381        } else if (!primaryFilters.equals(other.primaryFilters))
382          return false;
383        if (relatedEntities == null) {
384          if (other.relatedEntities != null)
385            return false;
386        } else if (!relatedEntities.equals(other.relatedEntities))
387          return false;
388        if (startTime == null) {
389          if (other.startTime != null)
390            return false;
391        } else if (!startTime.equals(other.startTime))
392          return false;
393        return true;
394      }
395    
396      @Override
397      public int compareTo(TimelineEntity other) {
398        int comparison = entityType.compareTo(other.entityType);
399        if (comparison == 0) {
400          long thisStartTime =
401              startTime == null ? Long.MIN_VALUE : startTime;
402          long otherStartTime =
403              other.startTime == null ? Long.MIN_VALUE : other.startTime;
404          if (thisStartTime > otherStartTime) {
405            return -1;
406          } else if (thisStartTime < otherStartTime) {
407            return 1;
408          } else {
409            return entityId.compareTo(other.entityId);
410          }
411        } else {
412          return comparison;
413        }
414      }
415    
416    }