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.Map;
|
||||||
import java.util.Set;
|
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")
|
@XmlRootElement(name = "entity")
|
||||||
@XmlAccessorType(XmlAccessType.NONE)
|
@XmlAccessorType(XmlAccessType.NONE)
|
||||||
@InterfaceAudience.Public
|
@InterfaceAudience.Public
|
||||||
@InterfaceStability.Unstable
|
@InterfaceStability.Unstable
|
||||||
public class TimelineEntity {
|
public class TimelineEntity implements Comparable<TimelineEntity> {
|
||||||
protected final static String SYSTEM_INFO_KEY_PREFIX = "SYSTEM_INFO_";
|
protected final static String SYSTEM_INFO_KEY_PREFIX = "SYSTEM_INFO_";
|
||||||
|
|
||||||
@XmlRootElement(name = "identifier")
|
@XmlRootElement(name = "identifier")
|
||||||
|
@ -77,6 +91,41 @@ public class TimelineEntity {
|
||||||
"type='" + type + '\'' +
|
"type='" + type + '\'' +
|
||||||
", id='" + id + '\'' + "]";
|
", 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;
|
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() {
|
protected TimelineEntity getReal() {
|
||||||
return real == null ? this : real;
|
return real == null ? this : real;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ import java.util.Map;
|
||||||
@XmlAccessorType(XmlAccessType.NONE)
|
@XmlAccessorType(XmlAccessType.NONE)
|
||||||
@InterfaceAudience.Public
|
@InterfaceAudience.Public
|
||||||
@InterfaceStability.Unstable
|
@InterfaceStability.Unstable
|
||||||
public class TimelineEvent {
|
public class TimelineEvent implements Comparable<TimelineEvent> {
|
||||||
private String id;
|
private String id;
|
||||||
private HashMap<String, Object> info = new HashMap<>();
|
private HashMap<String, Object> info = new HashMap<>();
|
||||||
private long timestamp;
|
private long timestamp;
|
||||||
|
@ -81,4 +81,43 @@ public class TimelineEvent {
|
||||||
public void setTimestamp(long timestamp) {
|
public void setTimestamp(long timestamp) {
|
||||||
this.timestamp = 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.clear();
|
||||||
this.values.putAll(values);
|
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);
|
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();
|
TimelineEvent event1 = new TimelineEvent();
|
||||||
event1.setId("test event id 1");
|
event1.setId("test event id 1");
|
||||||
event1.addInfo("test info key 1", "test info value 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);
|
event1.addInfo("test info key 3", true);
|
||||||
Assert.assertTrue(
|
Assert.assertTrue(
|
||||||
event1.getInfo().get("test info key 3") instanceof Boolean);
|
event1.getInfo().get("test info key 3") instanceof Boolean);
|
||||||
event1.setTimestamp(0L);
|
event1.setTimestamp(1L);
|
||||||
entity.addEvent(event1);
|
entity.addEvent(event1);
|
||||||
|
|
||||||
TimelineEvent event2 = new TimelineEvent();
|
TimelineEvent event2 = new TimelineEvent();
|
||||||
|
@ -119,9 +126,18 @@ public class TestTimelineServiceRecords {
|
||||||
event2.addInfo("test info key 3", true);
|
event2.addInfo("test info key 3", true);
|
||||||
Assert.assertTrue(
|
Assert.assertTrue(
|
||||||
event2.getInfo().get("test info key 3") instanceof Boolean);
|
event2.getInfo().get("test info key 3") instanceof Boolean);
|
||||||
event2.setTimestamp(1L);
|
event2.setTimestamp(2L);
|
||||||
entity.addEvent(event2);
|
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.setCreatedTime(0L);
|
||||||
entity.setModifiedTime(1L);
|
entity.setModifiedTime(1L);
|
||||||
entity.addRelatesToEntity("test type 2", "test id 2");
|
entity.addRelatesToEntity("test type 2", "test id 2");
|
||||||
|
@ -136,6 +152,22 @@ public class TestTimelineServiceRecords {
|
||||||
TimelineEntity entity2 = new TimelineEntity();
|
TimelineEntity entity2 = new TimelineEntity();
|
||||||
entities.addEntity(entity2);
|
entities.addEntity(entity2);
|
||||||
LOG.info(TimelineUtils.dumpTimelineRecordtoJSON(entities, true));
|
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
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue