<commit_before>/*
 * Part of the CCNx Java Library.
 *
 * Copyright (C) 2008-2011 Palo Alto Research Center, Inc.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation. 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details. You should have received
 * a copy of the GNU Lesser General Public License along with this library;
 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301 USA.
 */

package org.ccnx.ccn.protocol;

import java.io.Serializable;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

import org.ccnx.ccn.impl.encoding.CCNProtocolDTags;
import org.ccnx.ccn.impl.encoding.GenericXMLEncodable;
import org.ccnx.ccn.impl.encoding.XMLDecoder;
import org.ccnx.ccn.impl.encoding.XMLEncodable;
import org.ccnx.ccn.impl.encoding.XMLEncoder;
import org.ccnx.ccn.impl.support.DataUtils;
import org.ccnx.ccn.io.content.ContentDecodingException;
import org.ccnx.ccn.io.content.ContentEncodingException;
import org.ccnx.ccn.protocol.ContentNameProvider;

/**
 * ContentNames consist of a sequence of byte[] components which may not 
 * be assumed to follow any string encoding, or any other particular encoding.
 * The constructors therefore provide for creation only from byte[]s.
 * To create a ContentName from Strings, a client must call one of the static 
 * methods that implements a conversion.
 */
public class ContentName extends GenericXMLEncodable implements XMLEncodable, Comparable<ContentName>, Serializable, ContentNameProvider, Iterable<byte []> {

	private static final long serialVersionUID = 2754391169423477552L;

	/**
	 * Official CCN URI scheme.
	 */
	public static final String SCHEME = "ccnx:";

	/**
	 * This scheme has been deprecated, but we still want to accept it.
	 */
	public static final String ORIGINAL_SCHEME = "ccn:";

	public static final String SEPARATOR = "/";
	public static final ContentName ROOT = new ContentName(0, (ArrayList<byte []>)null);

	protected ArrayList<byte []>  _components;
	public static class DotDotComponent extends Exception { // Need to strip off a component
		private static final long serialVersionUID = 4667513234636853164L;
	}; 
	static final char HEX_DIGITS[] = {
		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
	};

	// Constructors
	public ContentName() {
		this(0, (ArrayList<byte[]>)null);
	}

	// support for name builder methods
	static abstract class StringParser {
		public abstract ArrayList<byte[]> parse(String s) throws MalformedContentNameStringException;
	}
	/**
	 * Allows a class to be included as an argument to a ContentName builder.
	 * @see builder
	 */
	public interface ComponentProvider {
		/**
		 * @return Fetches a component. The byte array that is returned must be immutable - i.e. never get changed.
		 * If there is any risk the byte array may be changed you must return a new copy of it.
		 */
		public byte[] getComponent();
	}
	private static final StringParser constructorStringParser = new StringParser(){
		@Override
		public ArrayList<byte[]> parse(String s) {
			try {
				return fromNative(s)._components;
			} catch (MalformedContentNameStringException e) {
				ArrayList<byte[]> components = new ArrayList<byte[]>(1);
				components.add(s.getBytes());
				return components;
			}
		}
	};
	private static final StringParser nativeStringParser = new StringParser(){
		@Override
		public ArrayList<byte[]> parse(String s) throws MalformedContentNameStringException {
			return fromNative(s)._components;
		}
	};
	private static final StringParser uriStringParser = new StringParser(){
		@Override
		public ArrayList<byte[]> parse(String s) throws MalformedContentNameStringException {
			return fromURI(s)._components;
		}
	};

	protected ContentName(ArrayList<byte[]> components) {
		_components = components;
	}

	/**
	 * Varargs name builder, Strings interpreted as Native.
	 * @see #builder(StringParser, Object[])
	 */
	public static ContentName fromNative(Object... args) throws MalformedContentNameStringException {
		return new ContentName(builder(nativeStringParser, args));
	}

	/**
	 * Varargs name builder, Strings interpreted as URI.
	 * @see #builder(StringParser, Object[])
	 */
	public static ContentName fromURI(Object... args) throws MalformedContentNameStringException {
		return new ContentName(builder(uriStringParser, args));
	}

	/**
	 * Varargs name builder, Strings that do not start with a / will be added as a single
	 * component. Strings that start with a / will be split at every / and added as a series
	 * of components. No URI decoding will be done, Strings components are kept raw.
	 * @see #builder(StringParser, Object[])
	 */
	public ContentName(Object... args) {
		try {
			_components = builder(constructorStringParser, args);
		} catch (MalformedContentNameStringException e) {
			// constructorStringParser won't throw an exception, this should never happen.
			throw new RuntimeException(e);
		}<commit_msg>refs #100499 ensure new ContentName(byte[] component) does what the user intends.<commit_after>/*
 * Part of the CCNx Java Library.
 *
 * Copyright (C) 2008-2011 Palo Alto Research Center, Inc.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation. 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details. You should have received
 * a copy of the GNU Lesser General Public License along with this library;
 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301 USA.
 */

package org.ccnx.ccn.protocol;

import java.io.Serializable;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

import org.ccnx.ccn.impl.encoding.CCNProtocolDTags;
import org.ccnx.ccn.impl.encoding.GenericXMLEncodable;
import org.ccnx.ccn.impl.encoding.XMLDecoder;
import org.ccnx.ccn.impl.encoding.XMLEncodable;
import org.ccnx.ccn.impl.encoding.XMLEncoder;
import org.ccnx.ccn.impl.support.DataUtils;
import org.ccnx.ccn.io.content.ContentDecodingException;
import org.ccnx.ccn.io.content.ContentEncodingException;
import org.ccnx.ccn.protocol.ContentNameProvider;

/**
 * ContentNames consist of a sequence of byte[] components which may not 
 * be assumed to follow any string encoding, or any other particular encoding.
 * The constructors therefore provide for creation only from byte[]s.
 * To create a ContentName from Strings, a client must call one of the static 
 * methods that implements a conversion.
 */
public class ContentName extends GenericXMLEncodable implements XMLEncodable, Comparable<ContentName>, Serializable, ContentNameProvider, Iterable<byte []> {

	private static final long serialVersionUID = 2754391169423477552L;

	/**
	 * Official CCN URI scheme.
	 */
	public static final String SCHEME = "ccnx:";

	/**
	 * This scheme has been deprecated, but we still want to accept it.
	 */
	public static final String ORIGINAL_SCHEME = "ccn:";

	public static final String SEPARATOR = "/";
	public static final ContentName ROOT = new ContentName(0, (ArrayList<byte []>)null);

	protected ArrayList<byte []>  _components;
	public static class DotDotComponent extends Exception { // Need to strip off a component
		private static final long serialVersionUID = 4667513234636853164L;
	}; 
	static final char HEX_DIGITS[] = {
		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
	};

	// Constructors
	public ContentName() {
		this(0, (ArrayList<byte[]>)null);
	}

	// support for name builder methods
	static abstract class StringParser {
		public abstract ArrayList<byte[]> parse(String s) throws MalformedContentNameStringException;
	}
	/**
	 * Allows a class to be included as an argument to a ContentName builder.
	 * @see builder
	 */
	public interface ComponentProvider {
		/**
		 * @return Fetches a component. The byte array that is returned must be immutable - i.e. never get changed.
		 * If there is any risk the byte array may be changed you must return a new copy of it.
		 */
		public byte[] getComponent();
	}
	private static final StringParser constructorStringParser = new StringParser(){
		@Override
		public ArrayList<byte[]> parse(String s) {
			try {
				return fromNative(s)._components;
			} catch (MalformedContentNameStringException e) {
				ArrayList<byte[]> components = new ArrayList<byte[]>(1);
				components.add(s.getBytes());
				return components;
			}
		}
	};
	private static final StringParser nativeStringParser = new StringParser(){
		@Override
		public ArrayList<byte[]> parse(String s) throws MalformedContentNameStringException {
			return fromNative(s)._components;
		}
	};
	private static final StringParser uriStringParser = new StringParser(){
		@Override
		public ArrayList<byte[]> parse(String s) throws MalformedContentNameStringException {
			return fromURI(s)._components;
		}
	};

	protected ContentName(ArrayList<byte[]> components) {
		_components = components;
	}

	/**
	 * This Constructor is required to avoid the varargs constructor interpreting
	 * a single byte[] as a list of separate byte arguments.
	 * @param component a single component. The data is cloned, so there is no restriction on
	 * its use after this call.
	 */
	public ContentName(byte[] component) {
		_components = new ArrayList<byte[]>(1);
		_components.add(component.clone());
	}

	/**
	 * Varargs name builder, Strings interpreted as Native.
	 * @see #builder(StringParser, Object[])
	 */
	public static ContentName fromNative(Object... args) throws MalformedContentNameStringException {
		return new ContentName(builder(nativeStringParser, args));
	}

	/**
	 * Varargs name builder, Strings interpreted as URI.
	 * @see #builder(StringParser, Object[])
	 */
	public static ContentName fromURI(Object... args) throws MalformedContentNameStringException {
		return new ContentName(builder(uriStringParser, args));
	}

	/**
	 * Varargs name builder, Strings that do not start with a / will be added as a single
	 * component. Strings that start with a / will be split at every / and added as a series
	 * of components. No URI decoding will be done, Strings components are kept raw.
	 * @see #builder(StringParser, Object[])
	 */
	public ContentName(Object... args) {
		try {
			_components = builder(constructorStringParser, args);
		} catch (MalformedContentNameStringException e) {
			// constructorStringParser won't throw an exception, this should never happen.
			throw new RuntimeException(e);
		}
{'fraction_non_alphanumeric': 0.0955322768376757, 'fraction_numerical': 0.013519563076372101, 'mean_word_length': 4.357314148681056, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 28, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3948838', 'n_tokens_mistral': 3364, 'n_tokens_neox': 3079, 'n_words': 1163}