All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.ripe.db.whois.common.rpsl.attrs.RangeOperation Maven / Gradle / Ivy

package net.ripe.db.whois.common.rpsl.attrs;

import org.apache.commons.lang.StringUtils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class RangeOperation {
    private static final Pattern RANGE_OPERATION_PATTERN = Pattern.compile("^\\^(?:[+-]|(\\d+)(?:\\-(\\d+))?)$");

    private final Integer n;
    private final Integer m;

    public static RangeOperation parse(final String value, final int prefixLength, final int maxRange) {
        if (StringUtils.isEmpty(value)) {
            return new RangeOperation(prefixLength, prefixLength);
        }

        final Matcher matcher = RANGE_OPERATION_PATTERN.matcher(value);
        if (!matcher.matches()) {
            throw new AttributeParseException("Invalid range operation", value);
        }

        //more specifics modes (^- and ^+): specify addresses more specific than the current, ^- excluding it, ^+ including it.
        //eg 1.1.1.1/8^- will also match 1.2.3.4/24, because the mask is *higher*, and the network portion matched by the original address mask (/8), is the same (1.x.x.x)
        
        if (value.startsWith("^-")) { //exclusive more specifics operator
            return new RangeOperation(prefixLength + 1, maxRange); //any prefix more specific than the current (so +1) and within the max length of the address type (eg 32 for ipv4)
        }

        if (value.startsWith("^+")) { //inclusive more specifics operator
            return new RangeOperation(prefixLength, maxRange);
        }

        
        //move on to length specified modes (^n and ^n-m)
        
        final Integer n = Integer.parseInt(matcher.group(1));
        if (n < prefixLength) {
            throw new AttributeParseException("n cannot be smaller than prefix length", value);
        }

        if (n > maxRange) {
            throw new AttributeParseException("n cannot be larger than max range" + n, value);
        }

        //look for ^n-m mode, and return with ^n mode if we don't find m.
        final Integer m = matcher.group(2) == null ? null : Integer.parseInt(matcher.group(2));
        if (m == null) {
            return new RangeOperation(n, n);
        }

        //validate m and return.
        
        if (m > maxRange) {
            throw new AttributeParseException("Invalid m: " + m, value);
        }

        if (n > m) {
            throw new AttributeParseException("Too large n: " + n, value);
        }

        return new RangeOperation(n, m);
    }

    private RangeOperation(final Integer n, final Integer m) {
        this.n = n;
        this.m = m;
    }

    public Integer getN() {
        return n;
    }

    public Integer getM() {
        return m;
    }
    
    @Override
    public int hashCode() { //TODO: untested
    	return toString().hashCode();
    }
    
    @Override
    public String toString() { //TODO: untested
    	return "RangeOperation [n:" + n + " m:" + m + "]";
    }
    
    @Override
    public boolean equals(final Object o) { //TODO: untested
    	if(o == this)
    		return true;
    	if(o == null || !(o instanceof RangeOperation))
    		return false;
    	else {
    		final RangeOperation that = (RangeOperation) o;
    		return m.equals(that.m) && n.equals(that.n);
    	}
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy