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.Private;
035    import org.apache.hadoop.classification.InterfaceAudience.Public;
036    import org.apache.hadoop.classification.InterfaceStability.Unstable;
037    
038    /**
039     * <p>
040     * The class that contains the the meta information of some conceptual entity
041     * and its related events. The entity can be an application, an application
042     * attempt, a container or whatever the user-defined object.
043     * </p>
044     * 
045     * <p>
046     * Primary filters will be used to index the entities in
047     * <code>TimelineStore</code>, such that users should carefully choose the
048     * information they want to store as the primary filters. The remaining can be
049     * stored as other information.
050     * </p>
051     */
052    @XmlRootElement(name = "entity")
053    @XmlAccessorType(XmlAccessType.NONE)
054    @Public
055    @Unstable
056    public class TimelineEntity implements Comparable<TimelineEntity> {
057    
058      private String entityType;
059      private String entityId;
060      private Long startTime;
061      private List<TimelineEvent> events = new ArrayList<TimelineEvent>();
062      private HashMap<String, Set<String>> relatedEntities =
063          new HashMap<String, Set<String>>();
064      private HashMap<String, Set<Object>> primaryFilters =
065          new HashMap<String, Set<Object>>();
066      private HashMap<String, Object> otherInfo =
067          new HashMap<String, Object>();
068      private String domainId;
069    
070      public TimelineEntity() {
071    
072      }
073    
074      /**
075       * Get the entity type
076       * 
077       * @return the entity type
078       */
079      @XmlElement(name = "entitytype")
080      public String getEntityType() {
081        return entityType;
082      }
083    
084      /**
085       * Set the entity type
086       * 
087       * @param entityType
088       *          the entity type
089       */
090      public void setEntityType(String entityType) {
091        this.entityType = entityType;
092      }
093    
094      /**
095       * Get the entity Id
096       * 
097       * @return the entity Id
098       */
099      @XmlElement(name = "entity")
100      public String getEntityId() {
101        return entityId;
102      }
103    
104      /**
105       * Set the entity Id
106       * 
107       * @param entityId
108       *          the entity Id
109       */
110      public void setEntityId(String entityId) {
111        this.entityId = entityId;
112      }
113    
114      /**
115       * Get the start time of the entity
116       * 
117       * @return the start time of the entity
118       */
119      @XmlElement(name = "starttime")
120      public Long getStartTime() {
121        return startTime;
122      }
123    
124      /**
125       * Set the start time of the entity
126       * 
127       * @param startTime
128       *          the start time of the entity
129       */
130      public void setStartTime(Long startTime) {
131        this.startTime = startTime;
132      }
133    
134      /**
135       * Get a list of events related to the entity
136       * 
137       * @return a list of events related to the entity
138       */
139      @XmlElement(name = "events")
140      public List<TimelineEvent> getEvents() {
141        return events;
142      }
143    
144      /**
145       * Add a single event related to the entity to the existing event list
146       * 
147       * @param event
148       *          a single event related to the entity
149       */
150      public void addEvent(TimelineEvent event) {
151        events.add(event);
152      }
153    
154      /**
155       * Add a list of events related to the entity to the existing event list
156       * 
157       * @param events
158       *          a list of events related to the entity
159       */
160      public void addEvents(List<TimelineEvent> events) {
161        this.events.addAll(events);
162      }
163    
164      /**
165       * Set the event list to the given list of events related to the entity
166       * 
167       * @param events
168       *          events a list of events related to the entity
169       */
170      public void setEvents(List<TimelineEvent> events) {
171        this.events = events;
172      }
173    
174      /**
175       * Get the related entities
176       * 
177       * @return the related entities
178       */
179      public Map<String, Set<String>> getRelatedEntities() {
180        return relatedEntities;
181      }
182    
183      // Required by JAXB
184      @Private
185      @XmlElement(name = "relatedentities")
186      public HashMap<String, Set<String>> getRelatedEntitiesJAXB() {
187        return relatedEntities;
188      }
189    
190      /**
191       * Add an entity to the existing related entity map
192       * 
193       * @param entityType
194       *          the entity type
195       * @param entityId
196       *          the entity Id
197       */
198      public void addRelatedEntity(String entityType, String entityId) {
199        Set<String> thisRelatedEntity = relatedEntities.get(entityType);
200        if (thisRelatedEntity == null) {
201          thisRelatedEntity = new HashSet<String>();
202          relatedEntities.put(entityType, thisRelatedEntity);
203        }
204        thisRelatedEntity.add(entityId);
205      }
206    
207      /**
208       * Add a map of related entities to the existing related entity map
209       * 
210       * @param relatedEntities
211       *          a map of related entities
212       */
213      public void addRelatedEntities(Map<String, Set<String>> relatedEntities) {
214        for (Entry<String, Set<String>> relatedEntity : relatedEntities.entrySet()) {
215          Set<String> thisRelatedEntity =
216              this.relatedEntities.get(relatedEntity.getKey());
217          if (thisRelatedEntity == null) {
218            this.relatedEntities.put(
219                relatedEntity.getKey(), relatedEntity.getValue());
220          } else {
221            thisRelatedEntity.addAll(relatedEntity.getValue());
222          }
223        }
224      }
225    
226      /**
227       * Set the related entity map to the given map of related entities
228       * 
229       * @param relatedEntities
230       *          a map of related entities
231       */
232      public void setRelatedEntities(
233          Map<String, Set<String>> relatedEntities) {
234        if (relatedEntities != null && !(relatedEntities instanceof HashMap)) {
235          this.relatedEntities = new HashMap<String, Set<String>>(relatedEntities);
236        } else {
237          this.relatedEntities = (HashMap<String, Set<String>>) relatedEntities;
238        }
239      }
240    
241      /**
242       * Get the primary filters
243       * 
244       * @return the primary filters
245       */
246      public Map<String, Set<Object>> getPrimaryFilters() {
247        return primaryFilters;
248      }
249    
250      // Required by JAXB
251      @Private
252      @XmlElement(name = "primaryfilters")
253      public HashMap<String, Set<Object>> getPrimaryFiltersJAXB() {
254        return primaryFilters;
255      }
256    
257      /**
258       * Add a single piece of primary filter to the existing primary filter map
259       * 
260       * @param key
261       *          the primary filter key
262       * @param value
263       *          the primary filter value
264       */
265      public void addPrimaryFilter(String key, Object value) {
266        Set<Object> thisPrimaryFilter = primaryFilters.get(key);
267        if (thisPrimaryFilter == null) {
268          thisPrimaryFilter = new HashSet<Object>();
269          primaryFilters.put(key, thisPrimaryFilter);
270        }
271        thisPrimaryFilter.add(value);
272      }
273    
274      /**
275       * Add a map of primary filters to the existing primary filter map
276       * 
277       * @param primaryFilters
278       *          a map of primary filters
279       */
280      public void addPrimaryFilters(Map<String, Set<Object>> primaryFilters) {
281        for (Entry<String, Set<Object>> primaryFilter : primaryFilters.entrySet()) {
282          Set<Object> thisPrimaryFilter =
283              this.primaryFilters.get(primaryFilter.getKey());
284          if (thisPrimaryFilter == null) {
285            this.primaryFilters.put(
286                primaryFilter.getKey(), primaryFilter.getValue());
287          } else {
288            thisPrimaryFilter.addAll(primaryFilter.getValue());
289          }
290        }
291      }
292    
293      /**
294       * Set the primary filter map to the given map of primary filters
295       * 
296       * @param primaryFilters
297       *          a map of primary filters
298       */
299      public void setPrimaryFilters(Map<String, Set<Object>> primaryFilters) {
300        if (primaryFilters != null && !(primaryFilters instanceof HashMap)) {
301          this.primaryFilters = new HashMap<String, Set<Object>>(primaryFilters);
302        } else {
303          this.primaryFilters = (HashMap<String, Set<Object>>) primaryFilters;
304        }
305      }
306    
307      /**
308       * Get the other information of the entity
309       * 
310       * @return the other information of the entity
311       */
312      public Map<String, Object> getOtherInfo() {
313        return otherInfo;
314      }
315    
316      // Required by JAXB
317      @Private
318      @XmlElement(name = "otherinfo")
319      public HashMap<String, Object> getOtherInfoJAXB() {
320        return otherInfo;
321      }
322    
323      /**
324       * Add one piece of other information of the entity to the existing other info
325       * map
326       * 
327       * @param key
328       *          the other information key
329       * @param value
330       *          the other information value
331       */
332      public void addOtherInfo(String key, Object value) {
333        this.otherInfo.put(key, value);
334      }
335    
336      /**
337       * Add a map of other information of the entity to the existing other info map
338       * 
339       * @param otherInfo
340       *          a map of other information
341       */
342      public void addOtherInfo(Map<String, Object> otherInfo) {
343        this.otherInfo.putAll(otherInfo);
344      }
345    
346      /**
347       * Set the other info map to the given map of other information
348       * 
349       * @param otherInfo
350       *          a map of other information
351       */
352      public void setOtherInfo(Map<String, Object> otherInfo) {
353        if (otherInfo != null && !(otherInfo instanceof HashMap)) {
354          this.otherInfo = new HashMap<String, Object>(otherInfo);
355        } else {
356          this.otherInfo = (HashMap<String, Object>) otherInfo;
357        }
358      }
359    
360      /**
361       * Get the ID of the domain that the entity is to be put
362       * 
363       * @return the domain ID
364       */
365      @XmlElement(name = "domain")
366      public String getDomainId() {
367        return domainId;
368      }
369    
370      /**
371       * Set the ID of the domain that the entity is to be put
372       * 
373       * @param domainId
374       *          the name space ID
375       */
376      public void setDomainId(String domainId) {
377        this.domainId = domainId;
378      }
379    
380      @Override
381      public int hashCode() {
382        // generated by eclipse
383        final int prime = 31;
384        int result = 1;
385        result = prime * result + ((entityId == null) ? 0 : entityId.hashCode());
386        result =
387            prime * result + ((entityType == null) ? 0 : entityType.hashCode());
388        result = prime * result + ((events == null) ? 0 : events.hashCode());
389        result = prime * result + ((otherInfo == null) ? 0 : otherInfo.hashCode());
390        result =
391            prime * result
392                + ((primaryFilters == null) ? 0 : primaryFilters.hashCode());
393        result =
394            prime * result
395                + ((relatedEntities == null) ? 0 : relatedEntities.hashCode());
396        result = prime * result + ((startTime == null) ? 0 : startTime.hashCode());
397        return result;
398      }
399    
400      @Override
401      public boolean equals(Object obj) {
402        // generated by eclipse
403        if (this == obj)
404          return true;
405        if (obj == null)
406          return false;
407        if (getClass() != obj.getClass())
408          return false;
409        TimelineEntity other = (TimelineEntity) obj;
410        if (entityId == null) {
411          if (other.entityId != null)
412            return false;
413        } else if (!entityId.equals(other.entityId))
414          return false;
415        if (entityType == null) {
416          if (other.entityType != null)
417            return false;
418        } else if (!entityType.equals(other.entityType))
419          return false;
420        if (events == null) {
421          if (other.events != null)
422            return false;
423        } else if (!events.equals(other.events))
424          return false;
425        if (otherInfo == null) {
426          if (other.otherInfo != null)
427            return false;
428        } else if (!otherInfo.equals(other.otherInfo))
429          return false;
430        if (primaryFilters == null) {
431          if (other.primaryFilters != null)
432            return false;
433        } else if (!primaryFilters.equals(other.primaryFilters))
434          return false;
435        if (relatedEntities == null) {
436          if (other.relatedEntities != null)
437            return false;
438        } else if (!relatedEntities.equals(other.relatedEntities))
439          return false;
440        if (startTime == null) {
441          if (other.startTime != null)
442            return false;
443        } else if (!startTime.equals(other.startTime))
444          return false;
445        return true;
446      }
447    
448      @Override
449      public int compareTo(TimelineEntity other) {
450        int comparison = entityType.compareTo(other.entityType);
451        if (comparison == 0) {
452          long thisStartTime =
453              startTime == null ? Long.MIN_VALUE : startTime;
454          long otherStartTime =
455              other.startTime == null ? Long.MIN_VALUE : other.startTime;
456          if (thisStartTime > otherStartTime) {
457            return -1;
458          } else if (thisStartTime < otherStartTime) {
459            return 1;
460          } else {
461            return entityId.compareTo(other.entityId);
462          }
463        } else {
464          return comparison;
465        }
466      }
467    
468    }