ClusterSpec { public boolean satisfies(ClusterSpec other) { if ( ! other.id.equals(this.id)) return false; if (other.type.isContent() || this.type.isContent()) return other.type.isContent() == this.type.isContent(); return other.type.equals(this.type); } private  ClusterSpec(Type type, Id id, Optional<Group> groupId, Version vespaVersion, boolean exclusive,
                        Optional<Id> combinedId, Optional<DockerImage> dockerImageRepo); Type type(); Id id(); Optional<DockerImage> dockerImageRepo(); Optional<String> dockerImage(); Version vespaVersion(); Optional<Group> group(); Optional<Id> combinedId(); boolean isExclusive(); ClusterSpec with(Optional<Group> newGroup); ClusterSpec exclusive(boolean exclusive); static Builder request(Type type, Id id); static Builder specification(Type type, Id id); @Override String toString(); @Override int hashCode(); @Override boolean equals(Object o); boolean satisfies(ClusterSpec other);  }
@Test public void testSatisfies() { var tests = Map.of( List.of(spec(ClusterSpec.Type.content, "id1"), spec(ClusterSpec.Type.content, "id2")), false, List.of(spec(ClusterSpec.Type.admin, "id1"), spec(ClusterSpec.Type.container, "id1")), false, List.of(spec(ClusterSpec.Type.admin, "id1"), spec(ClusterSpec.Type.content, "id1")), false, List.of(spec(ClusterSpec.Type.combined, "id1"), spec(ClusterSpec.Type.container, "id1")), false, List.of(spec(ClusterSpec.Type.combined, "id1"), spec(ClusterSpec.Type.content, "id1")), true, List.of(spec(ClusterSpec.Type.content, "id1"), spec(ClusterSpec.Type.content, "id1")), true ); tests.forEach((specs, satisfies) -> { var s1 = specs.get(0); var s2 = specs.get(1); assertEquals(s1 + (satisfies ? " satisfies " : " does not satisfy ") + s2, satisfies, s1.satisfies(s2)); assertEquals(s2 + (satisfies ? " satisfies " : " does not satisfy ") + s1, satisfies, s2.satisfies(s1)); }); }