<commit_before>package com.parc.ccn.data.query;

import java.util.Arrays;

import javax.xml.stream.XMLStreamException;

import com.parc.ccn.Library;
import com.parc.ccn.data.CompleteName;
import com.parc.ccn.data.ContentName;
import com.parc.ccn.data.ContentObject;
import com.parc.ccn.data.MalformedContentNameStringException;
import com.parc.ccn.data.security.PublisherID;
import com.parc.ccn.data.security.PublisherKeyID;
import com.parc.ccn.data.util.DataUtils;
import com.parc.ccn.data.util.GenericXMLEncodable;
import com.parc.ccn.data.util.XMLDecoder;
import com.parc.ccn.data.util.XMLEncodable;
import com.parc.ccn.data.util.XMLEncoder;
import com.parc.ccn.security.keys.TrustManager;

/**
 * This class represents all the allowed specializations
 * of queries recognized and supported (in a best-effort
 * fashion) at the CCN level.
 * 
 * Implement Comparable to make it much easier to store in
 * a Set and avoid duplicates.
 * 
 * <xs:complexType name="InterestType">
 *  <xs:sequence>
 *   <xs:element name="Name" type="NameType"/>
 *   <xs:element name="NameComponentCount" type="xs:nonNegativeInteger"
 *                       minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="PublisherID" type="PublisherIDType"
 *			minOccurs="0" maxOccurs="1"/>
 *    <xs:element name="Exclude" type="ExcludeType"
 *                       minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="OrderPreference" type="xs:nonNegativeInteger"
 *                       minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="AnswerOriginKind" type="xs:nonNegativeInteger"
 *                       minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="Scope" type="xs:nonNegativeInteger"
 *			minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="Count" type="xs:nonNegativeInteger"                                               
 *          minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="Nonce" type="Base64BinaryType"
 *			minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="ExperimentalResponseFilter" type="Base64BinaryType"
 *			minOccurs="0" maxOccurs="1"/>
 * </xs:sequence>
 * </xs:complexType>
 *
 * @author smetters
 *
 */
public class Interest extends GenericXMLEncodable implements XMLEncodable, Comparable<Interest> {
	
	// Used to remove spurious *'s
	public static final String RECURSIVE_POSTFIX = "*";
	
	public static final String INTEREST_ELEMENT = "Interest";
	public static final String ADDITIONAL_NAME_COMPONENTS = "AdditionalNameComponents";
	public static final String ORDER_PREFERENCE = "OrderPreference";
	public static final String ANSWER_ORIGIN_KIND = "AnswerOriginKind";
	public static final String SCOPE_ELEMENT = "Scope";
	public static final String COUNT_ELEMENT = "Count";
	public static final String NONCE_ELEMENT = "Nonce";
	public static final String RESPONSE_FILTER_ELEMENT = "ExperimentalResponseFilter";

	protected ContentName _name;
	protected Integer _additionalNameComponents;
	// DKS TODO can we really support a PublisherID here, or just a PublisherKeyID?
	protected PublisherID _publisher;
	protected ExcludeFilter _excludeFilter;
	protected Integer _orderPreference;
	protected Integer _answerOriginKind;
	protected Integer _scope;
	protected Integer _count;
	protected byte [] _nonce;
	protected byte [] _responseFilter;
	
	/**
	 * TODO: DKS figure out how to handle encoding faster,
	 * and how to handle shorter version of names without
	 * copying, particularly without 1.6 array ops.
	 * @param name
	 * @param authenticator
	 */
	public Interest(ContentName name, int additionalNameComponents,
			   PublisherID publisher) {
		_name = name;
		_additionalNameComponents = additionalNameComponents;
		_publisher = publisher;
	}

	public Interest(ContentName name, 
				   PublisherID publisher) {
		_name = name;
		_publisher = publisher;
	}
	
	public Interest(ContentName name) {
		this(name, null);
	}
	
	public Interest(String name) throws MalformedContentNameStringException {
		this(new ContentName(name), null);
	}

	public Interest() {} // for use by decoders

	public ContentName name() { return _name; }
	public void name(ContentName name) { _name = name; }
	
	public Integer additionalNameComponents() { return _additionalNameComponents;}
	public void additionalNameComponents(int additionalNameComponents) { _additionalNameComponents = additionalNameComponents; }

	public PublisherID publisherID() { return _publisher; }
	public void publisherID(PublisherID publisherID) { _publisher = publisherID; }
	
	public ExcludeFilter excludeFilter() { return _excludeFilter; }
	public void excludeFilter(ExcludeFilter excludeFilter) { _excludeFilter = excludeFilter; }
	
	public Integer orderPreference() { return _orderPreference;}
	public void orderPreference(int orderPreference) { _orderPreference = orderPreference; }
	
	public Integer answerOriginKind() { return _answerOriginKind; }
	public void answerOriginKind(int answerOriginKind) { _answerOriginKind = answerOriginKind; }
	
	public Integer scope() { return _scope; }
	public void scope(int scope) { _scope = scope; }

	public Integer count() { return _count; }
	public void count(int count) { _count = count; }

	public byte [] nonce() { return _nonce; }
	public void nonce(byte [] nonce) { _nonce = nonce; }
	
	public byte [] responseFilter() { return _responseFilter; }
	public void responseFilter(byte [] responseFilter) { _responseFilter = responseFilter; }
	
	public boolean matches(CompleteName result) {
		return matches(result.name(), (null != result.authenticator()) ? result.authenticator().publisherKeyID() : null);
	}
	
	public boolean matches(ContentObject result) {
		return matches(result.name(), (null != result.authenticator()) ? result.authenticator().publisherKeyID() : null);
	}

	/**
	 * Determine whether a piece of content matches this interest. We need
	 * to beef this up to deal with the more complex interest specs.
	 * 
	 * @param resultName
	 * @param resultPublisherKeyID
	 * @return
	 */
	public boolean matches(ContentName resultName, PublisherKeyID resultPublisherKeyID) {
		if (null == name() || null == resultName)
			return false; // null name() should not happen, null arg can
		// to get interest that matches everything, should
		// use / (ROOT)
		if (name().isPrefixOf(resultName)) {
			if (null != additionalNameComponents()) {
				// we know our specified name is a prefix of the result. 
				// the number of additional components must be this value
				// except at least resultName, and possibly name, do not contain
				// the extra content digest name component... for now assume
				// neither does, and count an exact match here as a 1-off
				// match (for resultName's missing content digest)
				int lengthDiff = resultName.count() - name().count() + 1;
				if (!additionalNameComponents().equals(lengthDiff)) {
					Library.logger().info("Interest match failed: " + lengthDiff + " more than the " + additionalNameComponents() + " components between expected " +
							name() + " and tested " + resultName);
					return false;
				}
			}
			if (null != publisherID()) {
				if (null == resultPublisherKeyID) {
					return false;
				}
				// Should this be more general?
				// TODO DKS handle issuer
				if (TrustManager.getTrustManager().matchesRole(publisherID(), resultPublisherKeyID)) {
					return true;
				}
			} else {
				return true;
			}
		}
		return false;
	}<commit_msg>Clean up comments<commit_after>package com.parc.ccn.data.query;

import java.util.Arrays;

import javax.xml.stream.XMLStreamException;

import com.parc.ccn.Library;
import com.parc.ccn.data.CompleteName;
import com.parc.ccn.data.ContentName;
import com.parc.ccn.data.ContentObject;
import com.parc.ccn.data.MalformedContentNameStringException;
import com.parc.ccn.data.security.PublisherID;
import com.parc.ccn.data.security.PublisherKeyID;
import com.parc.ccn.data.util.DataUtils;
import com.parc.ccn.data.util.GenericXMLEncodable;
import com.parc.ccn.data.util.XMLDecoder;
import com.parc.ccn.data.util.XMLEncodable;
import com.parc.ccn.data.util.XMLEncoder;
import com.parc.ccn.security.keys.TrustManager;

/**
 * This class represents all the allowed specializations
 * of queries recognized and supported (in a best-effort
 * fashion) at the CCN level.
 * 
 * Implement Comparable to make it much easier to store in
 * a Set and avoid duplicates.
 * 
 * <xs:complexType name="InterestType">
 *  <xs:sequence>
 *   <xs:element name="Name" type="NameType"/>
 *   <xs:element name="NameComponentCount" type="xs:nonNegativeInteger"
 *                       minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="PublisherID" type="PublisherIDType"
 *			minOccurs="0" maxOccurs="1"/>
 *    <xs:element name="Exclude" type="ExcludeType"
 *                       minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="OrderPreference" type="xs:nonNegativeInteger"
 *                       minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="AnswerOriginKind" type="xs:nonNegativeInteger"
 *                       minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="Scope" type="xs:nonNegativeInteger"
 *			minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="Count" type="xs:nonNegativeInteger"                                               
 *          minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="Nonce" type="Base64BinaryType"
 *			minOccurs="0" maxOccurs="1"/>
 *   <xs:element name="ExperimentalResponseFilter" type="Base64BinaryType"
 *			minOccurs="0" maxOccurs="1"/>
 * </xs:sequence>
 * </xs:complexType>
 *
 * @author smetters
 *
 */
public class Interest extends GenericXMLEncodable implements XMLEncodable, Comparable<Interest> {
	
	// Used to remove spurious *'s
	public static final String RECURSIVE_POSTFIX = "*";
	
	public static final String INTEREST_ELEMENT = "Interest";
	public static final String ADDITIONAL_NAME_COMPONENTS = "AdditionalNameComponents";
	public static final String ORDER_PREFERENCE = "OrderPreference";
	public static final String ANSWER_ORIGIN_KIND = "AnswerOriginKind";
	public static final String SCOPE_ELEMENT = "Scope";
	public static final String COUNT_ELEMENT = "Count";
	public static final String NONCE_ELEMENT = "Nonce";
	public static final String RESPONSE_FILTER_ELEMENT = "ExperimentalResponseFilter";

	protected ContentName _name;
	protected Integer _additionalNameComponents;
	// DKS TODO can we really support a PublisherID here, or just a PublisherKeyID?
	protected PublisherID _publisher;
	protected ExcludeFilter _excludeFilter;
	protected Integer _orderPreference;
	protected Integer _answerOriginKind;
	protected Integer _scope;
	protected Integer _count;
	protected byte [] _nonce;
	protected byte [] _responseFilter;
	
	/**
	 * TODO: DKS figure out how to handle encoding faster,
	 * and how to handle shorter version of names without
	 * copying, particularly without 1.6 array ops.
	 * @param name
	 * @param authenticator
	 */
	public Interest(ContentName name, int additionalNameComponents,
			   PublisherID publisher) {
		_name = name;
		_additionalNameComponents = additionalNameComponents;
		_publisher = publisher;
	}

	public Interest(ContentName name, 
				   PublisherID publisher) {
		_name = name;
		_publisher = publisher;
	}
	
	public Interest(ContentName name) {
		this(name, null);
	}
	
	public Interest(String name) throws MalformedContentNameStringException {
		this(new ContentName(name), null);
	}

	public Interest() {} // for use by decoders

	public ContentName name() { return _name; }
	public void name(ContentName name) { _name = name; }
	
	public Integer additionalNameComponents() { return _additionalNameComponents;}
	public void additionalNameComponents(int additionalNameComponents) { _additionalNameComponents = additionalNameComponents; }

	public PublisherID publisherID() { return _publisher; }
	public void publisherID(PublisherID publisherID) { _publisher = publisherID; }
	
	public ExcludeFilter excludeFilter() { return _excludeFilter; }
	public void excludeFilter(ExcludeFilter excludeFilter) { _excludeFilter = excludeFilter; }
	
	public Integer orderPreference() { return _orderPreference;}
	public void orderPreference(int orderPreference) { _orderPreference = orderPreference; }
	
	public Integer answerOriginKind() { return _answerOriginKind; }
	public void answerOriginKind(int answerOriginKind) { _answerOriginKind = answerOriginKind; }
	
	public Integer scope() { return _scope; }
	public void scope(int scope) { _scope = scope; }

	public Integer count() { return _count; }
	public void count(int count) { _count = count; }

	public byte [] nonce() { return _nonce; }
	public void nonce(byte [] nonce) { _nonce = nonce; }
	
	public byte [] responseFilter() { return _responseFilter; }
	public void responseFilter(byte [] responseFilter) { _responseFilter = responseFilter; }
	
	public boolean matches(CompleteName result) {
		return matches(result.name(), (null != result.authenticator()) ? result.authenticator().publisherKeyID() : null);
	}
	
	public boolean matches(ContentObject result) {
		return matches(result.name(), (null != result.authenticator()) ? result.authenticator().publisherKeyID() : null);
	}

	/**
	 * Determine whether a piece of content matches this interest. We need
	 * to beef this up to deal with the more complex interest specs.
	 * 
	 * @param resultName
	 * @param resultPublisherKeyID
	 * @return
	 */
	public boolean matches(ContentName resultName, PublisherKeyID resultPublisherKeyID) {
		if (null == name() || null == resultName)
			return false; // null name() should not happen, null arg can
		// to get interest that matches everything, should
		// use / (ROOT)
		if (name().isPrefixOf(resultName)) {
			if (null != additionalNameComponents()) {
				// we know our specified name is a prefix of the result. 
				// the number of additional components must be this value
				// we add 1 here for the missing "virtual digest" component
				// effectively on the end of resultName
				// TODO DKS this doesn't match if we specify the digest in the interest
				// though lengths will be handled properly (lengthDiff will come out 0,
				// which will match additionalNameComponents(); except we won't
				// compare to the content digest...)
				int lengthDiff = resultName.count() - name().count() + 1;
				if (!additionalNameComponents().equals(lengthDiff)) {
					Library.logger().info("Interest match failed: " + lengthDiff + " more than the " + additionalNameComponents() + " components between expected " +
							name() + " and tested " + resultName);
					return false;
				}
			}
			if (null != publisherID()) {
				if (null == resultPublisherKeyID) {
					return false;
				}
				// Should this be more general?
				// TODO DKS handle issuer
				if (TrustManager.getTrustManager().matchesRole(publisherID(), resultPublisherKeyID)) {
					return true;
				}
			} else {
				return true;
			}
		}
		return false;
	}
{'fraction_non_alphanumeric': 0.10503237992444685, 'fraction_numerical': 0.0035752833243389097, 'mean_word_length': 4.1511466296038915, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5316606', 'n_tokens_mistral': 4663, 'n_tokens_neox': 4199, 'n_words': 1218}