YARN-3836. add equals and hashCode to TimelineEntity and other classes in the data model (Li Lu via sjlee)
(cherry picked from commit 2d4a8f4563c06339717ca9410b2794754603fba3)
This commit is contained in:
parent
e27642abf4
commit
57d8dc2fb7
|
@ -31,11 +31,25 @@ import java.util.HashSet;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The basic timeline entity data structure for timeline service v2. Timeline
|
||||
* entity objects are not thread safe and should not be accessed concurrently.
|
||||
* All collection members will be initialized into empty collections. Two
|
||||
* timeline entities are equal iff. their type and id are identical.
|
||||
*
|
||||
* All non-primitive type, non-collection members will be initialized into null.
|
||||
* User should set the type and id of a timeline entity to make it valid (can be
|
||||
* checked by using the {@link #isValid()} method). Callers to the getters
|
||||
* should perform null checks for non-primitive type, non-collection members.
|
||||
*
|
||||
* Callers are recommended not to alter the returned collection objects from the
|
||||
* getters.
|
||||
*/
|
||||
@XmlRootElement(name = "entity")
|
||||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
@InterfaceAudience.Public
|
||||
@InterfaceStability.Unstable
|
||||
public class TimelineEntity {
|
||||
public class TimelineEntity implements Comparable<TimelineEntity> {
|
||||
protected final static String SYSTEM_INFO_KEY_PREFIX = "SYSTEM_INFO_";
|
||||
|
||||
@XmlRootElement(name = "identifier")
|
||||
|
@ -77,6 +91,41 @@ public class TimelineEntity {
|
|||
"type='" + type + '\'' +
|
||||
", id='" + id + '\'' + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||
result =
|
||||
prime * result + ((type == null) ? 0 : type.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (!(obj instanceof Identifier)) {
|
||||
return false;
|
||||
}
|
||||
Identifier other = (Identifier) obj;
|
||||
if (id == null) {
|
||||
if (other.getId() != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!id.equals(other.getId())) {
|
||||
return false;
|
||||
}
|
||||
if (type == null) {
|
||||
if (other.getType() != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!type.equals(other.getType())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private TimelineEntity real;
|
||||
|
@ -471,6 +520,44 @@ public class TimelineEntity {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return (getId() != null && getType() != null);
|
||||
}
|
||||
|
||||
// When get hashCode for a timeline entity, or check if two timeline entities
|
||||
// are equal, we only compare their identifiers (id and type)
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getIdentifier().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (!(obj instanceof TimelineEntity))
|
||||
return false;
|
||||
TimelineEntity other = (TimelineEntity) obj;
|
||||
return getIdentifier().equals(other.getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(TimelineEntity other) {
|
||||
int comparison = getType().compareTo(other.getType());
|
||||
if (comparison == 0) {
|
||||
if (getCreatedTime() > other.getCreatedTime()) {
|
||||
// Order by created time desc
|
||||
return -1;
|
||||
} else if (getCreatedTime() < other.getCreatedTime()) {
|
||||
return 1;
|
||||
} else {
|
||||
return getId().compareTo(other.getId());
|
||||
}
|
||||
} else {
|
||||
return comparison;
|
||||
}
|
||||
}
|
||||
|
||||
protected TimelineEntity getReal() {
|
||||
return real == null ? this : real;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.util.Map;
|
|||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
@InterfaceAudience.Public
|
||||
@InterfaceStability.Unstable
|
||||
public class TimelineEvent {
|
||||
public class TimelineEvent implements Comparable<TimelineEvent> {
|
||||
private String id;
|
||||
private HashMap<String, Object> info = new HashMap<>();
|
||||
private long timestamp;
|
||||
|
@ -81,4 +81,43 @@ public class TimelineEvent {
|
|||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return (id != null && timestamp != 0L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (int) (timestamp ^ (timestamp >>> 32));
|
||||
result = 31 * result + id.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof TimelineEvent))
|
||||
return false;
|
||||
|
||||
TimelineEvent event = (TimelineEvent) o;
|
||||
|
||||
if (timestamp != event.timestamp)
|
||||
return false;
|
||||
if (!id.equals(event.id)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(TimelineEvent other) {
|
||||
if (timestamp > other.timestamp) {
|
||||
return -1;
|
||||
} else if (timestamp < other.timestamp) {
|
||||
return 1;
|
||||
} else {
|
||||
return id.compareTo(other.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,4 +124,34 @@ public class TimelineMetric {
|
|||
this.values.clear();
|
||||
this.values.putAll(values);
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return (id != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id.hashCode();
|
||||
result = 31 * result + type.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Only check if type and id are equal
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof TimelineMetric))
|
||||
return false;
|
||||
|
||||
TimelineMetric m = (TimelineMetric) o;
|
||||
|
||||
if (!id.equals(m.id)) {
|
||||
return false;
|
||||
}
|
||||
if (type != m.type) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,6 +100,13 @@ public class TestTimelineServiceRecords {
|
|||
}
|
||||
entity.addMetric(metric2);
|
||||
|
||||
TimelineMetric metric3 = new TimelineMetric(TimelineMetric.Type.SINGLE_VALUE);
|
||||
metric3.setId("test metric id 1");
|
||||
metric3.addValue(4L, (short) 4);
|
||||
Assert.assertEquals("metric3 should equal to metric2! ", metric3, metric2);
|
||||
Assert.assertNotEquals("metric1 should not equal to metric2! ",
|
||||
metric1, metric2);
|
||||
|
||||
TimelineEvent event1 = new TimelineEvent();
|
||||
event1.setId("test event id 1");
|
||||
event1.addInfo("test info key 1", "test info value 1");
|
||||
|
@ -108,7 +115,7 @@ public class TestTimelineServiceRecords {
|
|||
event1.addInfo("test info key 3", true);
|
||||
Assert.assertTrue(
|
||||
event1.getInfo().get("test info key 3") instanceof Boolean);
|
||||
event1.setTimestamp(0L);
|
||||
event1.setTimestamp(1L);
|
||||
entity.addEvent(event1);
|
||||
|
||||
TimelineEvent event2 = new TimelineEvent();
|
||||
|
@ -119,9 +126,18 @@ public class TestTimelineServiceRecords {
|
|||
event2.addInfo("test info key 3", true);
|
||||
Assert.assertTrue(
|
||||
event2.getInfo().get("test info key 3") instanceof Boolean);
|
||||
event2.setTimestamp(1L);
|
||||
event2.setTimestamp(2L);
|
||||
entity.addEvent(event2);
|
||||
|
||||
Assert.assertFalse("event1 should not equal to event2! ",
|
||||
event1.equals(event2));
|
||||
TimelineEvent event3 = new TimelineEvent();
|
||||
event3.setId("test event id 1");
|
||||
event3.setTimestamp(1L);
|
||||
Assert.assertEquals("event1 should equal to event3! ", event3, event1);
|
||||
Assert.assertNotEquals("event1 should not equal to event2! ",
|
||||
event1, event2);
|
||||
|
||||
entity.setCreatedTime(0L);
|
||||
entity.setModifiedTime(1L);
|
||||
entity.addRelatesToEntity("test type 2", "test id 2");
|
||||
|
@ -136,6 +152,22 @@ public class TestTimelineServiceRecords {
|
|||
TimelineEntity entity2 = new TimelineEntity();
|
||||
entities.addEntity(entity2);
|
||||
LOG.info(TimelineUtils.dumpTimelineRecordtoJSON(entities, true));
|
||||
|
||||
Assert.assertFalse("entity 1 should not be valid without type and id",
|
||||
entity1.isValid());
|
||||
entity1.setId("test id 2");
|
||||
entity1.setType("test type 2");
|
||||
entity2.setId("test id 1");
|
||||
entity2.setType("test type 1");
|
||||
|
||||
Assert.assertEquals("Timeline entity should equal to entity2! ",
|
||||
entity, entity2);
|
||||
Assert.assertNotEquals("entity1 should not equal to entity! ",
|
||||
entity1, entity);
|
||||
Assert.assertEquals("entity should be less than entity1! ",
|
||||
entity1.compareTo(entity), 1);
|
||||
Assert.assertEquals("entity's hash code should be -28727840 but not "
|
||||
+ entity.hashCode(), entity.hashCode(), -28727840);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue