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
019package org.apache.hadoop.yarn.api.records.timeline;
020
021import java.util.ArrayList;
022import java.util.HashMap;
023import java.util.HashSet;
024import java.util.List;
025import java.util.Map;
026import java.util.Map.Entry;
027import java.util.Set;
028
029import javax.xml.bind.annotation.XmlAccessType;
030import javax.xml.bind.annotation.XmlAccessorType;
031import javax.xml.bind.annotation.XmlElement;
032import javax.xml.bind.annotation.XmlRootElement;
033
034import org.apache.hadoop.classification.InterfaceAudience.Private;
035import org.apache.hadoop.classification.InterfaceAudience.Public;
036import 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
056public 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}