package org.batfish.datamodel;
import java.util.List;
import org.batfish.common.util.ComparableStructure;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.kjetland.jackson.jsonSchema.annotations.JsonSchemaDescription;
@JsonSchemaDescription("An access-list used to filter IPV4 packets")
public class IpAccessList extends ComparableStructure<String> {
private static final String LINES_VAR = "lines";
private static final long serialVersionUID = 1L;
static boolean bothNullOrSameName(IpAccessList a, IpAccessList b) {
if (a == null && b == null) {
return true;
}
else if (a != null && b != null) {
return a.getName().equals(b.getName());
}
else {
return false;
}
}
static boolean bothNullOrUnorderedEqual(IpAccessList a, IpAccessList b) {
if (a == null && b == null) {
return true;
}
else if (a != null && b != null) {
return a.unorderedEqual(b);
}
else {
return false;
}
}
private List<IpAccessListLine> _lines;
@JsonCreator
public IpAccessList(@JsonProperty(NAME_VAR) String name) {
super(name);
}
public IpAccessList(String name, List<IpAccessListLine> lines) {
super(name);
_lines = lines;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
IpAccessList other = (IpAccessList) obj;
return other._lines.equals(_lines);
}
public FilterResult filter(Flow flow) {
for (int i = 0; i < _lines.size(); i++) {
IpAccessListLine line = _lines.get(i);
if (line.matches(flow)) {
return new FilterResult(i, line.getAction());
}
}
return new FilterResult(null, LineAction.REJECT);
}
@JsonProperty(LINES_VAR)
@JsonPropertyDescription("The lines against which to check an IPV4 packet")
public List<IpAccessListLine> getLines() {
return _lines;
}
private boolean noDenyOrLastDeny(IpAccessList acl) {
int count = 0;
for (IpAccessListLine line : acl.getLines()) {
if (line.getAction() == LineAction.REJECT
&& count < acl.getLines().size() - 1) {
return false;
}
count++;
}
return true;
}
@JsonProperty(LINES_VAR)
public void setLines(List<IpAccessListLine> lines) {
_lines = lines;
}
@Override
public String toString() {
String output = super.toString() + "\n" + "Identifier: " + _key;
for (IpAccessListLine line : _lines) {
output += "\n" + line;
}
return output;
}
public boolean unorderedEqual(Object obj) {
if (this == obj) {
return true;
}
if (this.equals(obj)) {
return true;
}
IpAccessList other = (IpAccessList) obj;
if (this.getLines().size() != other.getLines().size()) {
return false;
}
// Unordered check is valid only if there is no deny OR if there is only
// one, at the
// end, in both lists.
if (!noDenyOrLastDeny(this) || !noDenyOrLastDeny(other)) {
return false;
}
for (IpAccessListLine line : this.getLines()) {
if (!other.getLines().contains(line)) {
return false;
}
}
return true;
}
}