/*
 * PrefixRankedBarNonlinearPattern.h
 *
 * This file is part of Algorithms library toolkit.
 * Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz)

 * Algorithms library toolkit is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * Algorithms library toolkit 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 General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with Algorithms library toolkit.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  Created on: Jul 20, 2016
 *      Author: Jan Travnicek
 */

#ifndef PREFIX_RANKED_BAR_NONLINEAR_PATTERN_H_
#define PREFIX_RANKED_BAR_NONLINEAR_PATTERN_H_

#include <common/DefaultSymbolType.h>

namespace tree {

template < class SymbolType = DefaultSymbolType >
class PrefixRankedBarNonlinearPattern;

} /* namespace tree */

#include <sstream>

#include <alib/set>
#include <alib/vector>
#include <alib/tree>
#include <alib/algorithm>
#include <alib/deque>

#include <core/components.hpp>
#include <common/ranked_symbol.hpp>

#include <tree/TreeException.h>
#include <tree/common/TreeAuxiliary.h>

#include <alphabet/BarSymbol.h>
#include <alphabet/VariablesBarSymbol.h>
#include <alphabet/WildcardSymbol.h>

#include <core/normalize.hpp>
#include <tree/common/TreeNormalize.h>

#include <string/LinearString.h>

#include "PrefixRankedBarTree.h"
#include "PrefixRankedBarPattern.h"
#include "RankedTree.h"
#include "RankedPattern.h"
#include "RankedNonlinearPattern.h"

namespace tree {

class GeneralAlphabet;
class SubtreeWildcard;
class BarSymbols;
class VariablesBarSymbol;
class NonlinearAlphabet;

/**
 * \brief
 * Nonlinear tree pattern represented as linear sequece as result of preorder traversal with additional bar symbols. The representation is so called ranked, therefore it consists of ranked symbols (bars are ranked as well). The rank of the ranked symbol needs be to compatible with unsigned integer. Additionally the pattern contains a special wildcard symbol representing any subtree and nonlinear variables each to represent same subtree (in the particular occurrence in a tree). To match the wildcard and nonlinear variable, special bar symbol called variables bar is present as well.
 *
 * The bars represent end mark of all subpatterns in the notation.
 *
 * \details
 * T = (A, B \subset A, C, W \in ( A \minus B ), V \in ( A \minus B), Wb \in B ),
 * A (Alphabet) = finite set of ranked symbols,
 * B (Bars) = finite set of ranked symbols representing bars,
 * C (Content) = linear representation of the pattern content
 * W (Wildcard) = special symbol representing any subtree
 * V (Variables) = finite set of special symbols each representing same subtree
 * Wb (VariablesBar) = special bar symbol to match wildcard
 *
 * \tparam SymbolType used for the symbol part of the ranked symbol
 */
template < class SymbolType >
class PrefixRankedBarNonlinearPattern final : public ext::CompareOperators < PrefixRankedBarNonlinearPattern < SymbolType > >, public core::Components < PrefixRankedBarNonlinearPattern < SymbolType >, ext::set < common::ranked_symbol < SymbolType > >, component::Set, std::tuple < GeneralAlphabet, NonlinearAlphabet, BarSymbols >, common::ranked_symbol < SymbolType >, component::Value, std::tuple < SubtreeWildcard, VariablesBarSymbol > > {
	/**
	 * Linear representation of the pattern content.
	 */
	ext::vector < common::ranked_symbol < SymbolType > > m_Data;

	/**
	 * Checker of validity of the representation of the ettern
	 *
	 * \throws TreeException when new pattern representation is not valid
	 */
	void arityChecksum ( const ext::vector < common::ranked_symbol < SymbolType > > & data );

public:
	/**
	 * \brief Creates a new instance of the pattern with concrete alphabet, bars, content, wildcard, nonlinear variables, and variables bar.
	 *
	 * \param bars the initial bar set
	 * \param variablesBar the initial variables bar
	 * \param subtreeWildcard the wildcard symbol
	 * \param nonlinearVariables the set of nonlinear variables
	 * \param alphabet the initial alphabet of the pattern
	 * \param data the initial pattern in linear representation
	 */
	explicit PrefixRankedBarNonlinearPattern ( ext::set < common::ranked_symbol < SymbolType > > bars, common::ranked_symbol < SymbolType > variablesBar, common::ranked_symbol < SymbolType > subtreeWildcard, ext::set < common::ranked_symbol < SymbolType > > nonlinearVariables, ext::set < common::ranked_symbol < SymbolType > > alphabet, ext::vector < common::ranked_symbol < SymbolType > > data );

	/**
	 * \brief Creates a new instance of the pattern with concrete bars, content, wildcard, nonlinear variables, and variables bar. The alphabet is deduced from the content.
	 *
	 * \param bars the initial bar set
	 * \param variablesBar the initial variables bar
	 * \param subtreeWildcard the wildcard symbol
	 * \param nonlinearVariables the set of nonlinear variables
	 * \param data the initial pattern in linear representation
	 */
	explicit PrefixRankedBarNonlinearPattern ( ext::set < common::ranked_symbol < SymbolType > > bars, common::ranked_symbol < SymbolType > variablesBar, common::ranked_symbol < SymbolType > subtreeWildcard, ext::set < common::ranked_symbol < SymbolType > > nonlinearVariables, ext::vector < common::ranked_symbol < SymbolType > > data );

	/**
	 * \brief Creates a new instance of the pattern with concrete bars, content, wildcard, and variables bar. The alphabet is deduced from the content. Nonlinear variables are defaultly constructed to empty set.
	 *
	 * \param bars the initial bar set
	 * \param variablesBar the initial variables bar
	 * \param subtreeWildcard the wildcard symbol
	 * \param data the initial pattern in linear representation
	 */
	explicit PrefixRankedBarNonlinearPattern ( ext::set < common::ranked_symbol < SymbolType > > bars, common::ranked_symbol < SymbolType > variablesBar, common::ranked_symbol < SymbolType > subtreeWildcard, ext::vector < common::ranked_symbol < SymbolType > > data );

	/**
	 * \brief Creates a new instance of the pattern based on the RankedTree. The linear representation is constructed (including bars) by preorder traversal on the tree parameter. Symbol part of bars and variables bar are provided as parameters. The subtree wildcard is defaultly constructed and nonlinear variables are defaultly constructed to empty set.
	 *
	 * \param barBase the symbol part of all bars
	 * \param variablesBar the initial variables bar
	 * \param tree representation of a tree.
	 */
	explicit PrefixRankedBarNonlinearPattern ( SymbolType barBase, common::ranked_symbol < SymbolType > variablesBar, const RankedTree < SymbolType > & tree );

	/**
	 * \brief Creates a new instance of the pattern based on the RankedPattern. The linear representation is constructed (including bars) by preorder traversal on the tree parameter. Symbol part of bars and variables bar are provided as parameters. The subtree wildcard is provided by the pattern parameter and nonlinear variables are defaultly constructed to empty set.
	 *
	 * \param barBase the symbol part of all bars
	 * \param variablesBar the initial variables bar
	 * \param tree representation of a pattern.
	 */
	explicit PrefixRankedBarNonlinearPattern ( SymbolType barBase, common::ranked_symbol < SymbolType > variablesBar, const RankedPattern < SymbolType > & tree );

	/**
	 * \brief Creates a new instance of the pattern based on the RankedNonlinearPattern. The linear representation is constructed (including bars) by preorder traversal on the tree parameter. Symbol part of bars and variables bar are provided as parameters. The subtree wildcard and nonlinear variables are provided by the pattern parameter.
	 *
	 * \param barBase the symbol part of all bars
	 * \param variablesBar the initial variables bar
	 * \param tree representation of a pattern.
	 */
	explicit PrefixRankedBarNonlinearPattern ( SymbolType barBase, common::ranked_symbol < SymbolType > variablesBar, const RankedNonlinearPattern < SymbolType > & tree );

	/**
	 * \brief Creates a new instance of the pattern based on the PrefixRankedBarTree. The linear representation is copied from tree. Bars and alphabet as well. Variables bar, subtree wildcard are defaultly constructed and nonlinear variables are defaultly constructed to empty set.
	 *
	 * \param tree representation of a tree.
	 */
	explicit PrefixRankedBarNonlinearPattern ( const PrefixRankedBarTree < SymbolType > & tree );

	/**
	 * \brief Creates a new instance of the pattern based on the PrefixRankedBarPattern. The linear representation is copied from tree. Subtree wildcard, variables bar, bars, and alphabet as well. Nonlinear variables are defaultly constructed to empty set.
	 *
	 * \param tree representation of a tree.
	 */
	explicit PrefixRankedBarNonlinearPattern ( const PrefixRankedBarPattern < SymbolType > & tree );

	/**
	 * \brief Creates a new instance of the pattern based on the RankedTree. The linear representation is constructed (including bars) by preorder traversal on the tree parameter. Bars are computed to match symbols used in the representation from RankedPattern. Subtree wildcard and variables bar are defaultly constructed. Nonlinear variables are defaultly constructed to empty set.
	 *
	 * \param tree RankedTree representation of a tree.
	 */
	explicit PrefixRankedBarNonlinearPattern ( const RankedTree < SymbolType > & tree );

	/**
	 * \brief Creates a new instance of the pattern based on the RankedPattern. The linear representation is constructed (including bars) by preorder traversal on the tree parameter. Bars are computed to match symbols used in the representation from RankedPattern. Subtree wildcard is copied from the pattern. Variables bar is defaultly constructed. Nonlinear variables are defaultly constructed to empty set.
	 *
	 * \param tree RankedTree representation of a tree.
	 */
	explicit PrefixRankedBarNonlinearPattern ( const RankedPattern < SymbolType > & tree );

	/**
	 * \brief Creates a new instance of the pattern based on the NonlinearRankedPattern. The linear representation is constructed (including bars) by preorder traversal on the tree parameter. Bars are computed to match symbols used in the representation from RankedPattern. Subtree wildcard and nonlinear variables are copied from the pattern. Variables bar is defaultly constructed.
	 *
	 * \param tree RankedTree representation of a tree.
	 */
	explicit PrefixRankedBarNonlinearPattern ( const RankedNonlinearPattern < SymbolType > & tree );

	/**
	 * Getter of the alphabet.
	 *
	 * \returns the alphabet of the pattern
	 */
	const ext::set < common::ranked_symbol < SymbolType > > & getAlphabet ( ) const & {
		return this->template accessComponent < GeneralAlphabet > ( ).get ( );
	}

	/**
	 * Getter of the alphabet.
	 *
	 * \returns the alphabet of the pattern
	 */
	ext::set < common::ranked_symbol < SymbolType > > && getAlphabet ( ) && {
		return std::move ( this->template accessComponent < GeneralAlphabet > ( ).get ( ) );
	}

	/**
	 * Adder of an alphabet symbols.
	 *
	 * \param symbols the new symbols to be added to the alphabet
	 */
	void extendAlphabet ( const ext::set < common::ranked_symbol < SymbolType > > & symbols ) {
		this->template accessComponent < GeneralAlphabet > ( ).add ( symbols );
	}

	/**
	 * Getter of the bar set.
	 *
	 * \returns the bar set of the pattern
	 */
	const ext::set < common::ranked_symbol < SymbolType > > & getBars ( ) const & {
		return this->template accessComponent < BarSymbols > ( ).get ( );
	}

	/**
	 * Getter of the bar set.
	 *
	 * \returns the bar set of the pattern
	 */
	ext::set < common::ranked_symbol < SymbolType > > && getBars ( ) && {
		return std::move ( this->template accessComponent < BarSymbols > ( ).get ( ) );
	}

	/**
	 * Adder of symbols to a bar set.
	 *
	 * \param symbols the new symbols to be added to the bar set
	 */
	void extendBars ( const ext::set < common::ranked_symbol < SymbolType > > & bars ) {
		this->template accessComponent < BarSymbols > ( ).add ( bars );
	}

	/**
	 * Getter of the wildcard symbol.
	 *
	 * \returns the wildcard symbol of the pattern
	 */
	const common::ranked_symbol < SymbolType > & getSubtreeWildcard ( ) const & {
		return this->template accessComponent < SubtreeWildcard > ( ).get ( );
	}

	/**
	 * Getter of the wildcard symbol.
	 *
	 * \returns the wildcard symbol of the pattern
	 */
	common::ranked_symbol < SymbolType > && getSubtreeWildcard ( ) && {
		return std::move ( this->template accessComponent < SubtreeWildcard > ( ).get ( ) );
	}

	/**
	 * Getter of the nonlinear variables.
	 *
	 * \returns the nonlinear variables of the pattern
	 */
	const ext::set < common::ranked_symbol < SymbolType > > & getNonlinearVariables ( ) const & {
		return this->template accessComponent < NonlinearAlphabet > ( ).get ( );
	}

	/**
	 * Getter of the nonlinear variables.
	 *
	 * \returns the nonlinear variables of the pattern
	 */
	ext::set < common::ranked_symbol < SymbolType > > && getNonlinearVariables ( ) && {
		return std::move ( this->template accessComponent < NonlinearAlphabet > ( ).get ( ) );
	}

	/**
	 * Getter of the variables bar.
	 *
	 * \returns the variables bar of the pattern
	 */
	const common::ranked_symbol < SymbolType > & getVariablesBar ( ) const & {
		return this->template accessComponent < VariablesBarSymbol > ( ).get ( );
	}

	/**
	 * Getter of the variables bar.
	 *
	 * \returns the variables bar of the pattern
	 */
	common::ranked_symbol < SymbolType > && getVariablesBar ( ) && {
		return std::move ( this->template accessComponent < VariablesBarSymbol > ( ).get ( ) );
	}

	/**
	 * Getter of the pattern representation.
	 *
	 * \return List of symbols forming the linear representation of the pattern.
	 */
	const ext::vector < common::ranked_symbol < SymbolType > > & getContent ( ) const &;

	/**
	 * Getter of the pattern representation.
	 *
	 * \return List of symbols forming the linear representation of the pattern.
	 */
	ext::vector < common::ranked_symbol < SymbolType > > && getContent ( ) &&;

	/**
	 * Setter of the representation of the pattern.
	 *
	 * \throws TreeException when new pattern representation is not valid or when symbol of the representation are not present in the alphabet
	 *
	 * \param data new List of symbols forming the representation of the pattern.
	 */
	void setContent ( ext::vector < common::ranked_symbol < SymbolType > > data );

	/**
	 * @return true if pattern is an empty word (vector length is 0). The method is present to allow compatibility with strings. Tree is never empty in this datatype.
	 */
	bool isEmpty ( ) const;

	/**
	 * The actual compare method
	 *
	 * \param other the other instance
	 *
	 * \returns the actual relation between two by type same pattern instances
	 */
	int compare ( const PrefixRankedBarNonlinearPattern & other ) const;

	/**
	 * Print this object as raw representation to ostream.
	 *
	 * \param out ostream where to print
	 * \param instance object to print
	 *
	 * \returns modified output stream
	 */
	friend std::ostream & operator << ( std::ostream & out, const PrefixRankedBarNonlinearPattern & instance ) {
		out << "(PrefixRankedBarNonlinearPattern ";
		out << "alphabet = " << instance.getAlphabet ( );
		out << "bars = " << instance.getBars ( );
		out << "variablesBar = " << instance.getVariablesBar ( );
		out << "content = " << instance.getContent ( );
		out << "nonlinearVariables = " << instance.getNonlinearVariables ( );
		out << "subtreeWildcard = " << instance.getSubtreeWildcard ( );
		out << ")";
		return out;
	}

	/**
	 * Casts this instance to as compact as possible string representation.
	 *
	 * \returns string representation of the object
	 */
	explicit operator std::string ( ) const;

	/**
	 * \brief Creates a new instance of the string from a linear representation of a tree
	 *
	 * \returns tree casted to string
	 */
	explicit operator string::LinearString < common::ranked_symbol < SymbolType > > ( ) const {
		return string::LinearString < common::ranked_symbol < SymbolType > > ( getAlphabet ( ), getContent ( ) );
	}
};

template < class SymbolType >
PrefixRankedBarNonlinearPattern < SymbolType >::PrefixRankedBarNonlinearPattern ( ext::set < common::ranked_symbol < SymbolType > > bars, common::ranked_symbol < SymbolType > variablesBar, common::ranked_symbol < SymbolType > subtreeWildcard, ext::set < common::ranked_symbol < SymbolType > > nonlinearVariables, ext::set < common::ranked_symbol < SymbolType > > alphabet, ext::vector < common::ranked_symbol < SymbolType > > data ) : core::Components < PrefixRankedBarNonlinearPattern, ext::set < common::ranked_symbol < SymbolType > >, component::Set, std::tuple < GeneralAlphabet, NonlinearAlphabet, BarSymbols >, common::ranked_symbol < SymbolType >, component::Value, std::tuple < SubtreeWildcard, VariablesBarSymbol > > ( std::move ( alphabet ), std::move ( nonlinearVariables ), std::move ( bars ), std::move ( subtreeWildcard ), std::move ( variablesBar ) ) {
	setContent ( std::move ( data ) );
}

template < class SymbolType >
PrefixRankedBarNonlinearPattern < SymbolType >::PrefixRankedBarNonlinearPattern ( ext::set < common::ranked_symbol < SymbolType > > bars, common::ranked_symbol < SymbolType > variablesBar, common::ranked_symbol < SymbolType > subtreeWildcard, ext::set < common::ranked_symbol < SymbolType > > nonlinearVariables, ext::vector < common::ranked_symbol < SymbolType > > data ) : PrefixRankedBarNonlinearPattern ( bars, variablesBar, subtreeWildcard, nonlinearVariables, ext::set < common::ranked_symbol < SymbolType > > ( data.begin ( ), data.end ( ) ) + bars + ext::set < common::ranked_symbol < SymbolType > > { variablesBar, subtreeWildcard } + nonlinearVariables, data ) {
}

template < class SymbolType >
PrefixRankedBarNonlinearPattern < SymbolType >::PrefixRankedBarNonlinearPattern ( ext::set < common::ranked_symbol < SymbolType > > bars, common::ranked_symbol < SymbolType > variablesBar, common::ranked_symbol < SymbolType > subtreeWildcard, ext::vector < common::ranked_symbol < SymbolType > > data ) : PrefixRankedBarNonlinearPattern ( bars, variablesBar, subtreeWildcard, { }, ext::set < common::ranked_symbol < SymbolType > > ( data.begin ( ), data.end ( ) ) + bars + ext::set < common::ranked_symbol < SymbolType > > { variablesBar, subtreeWildcard }, data ) {
}

template < class SymbolType >
PrefixRankedBarNonlinearPattern < SymbolType >::PrefixRankedBarNonlinearPattern ( SymbolType barBase, common::ranked_symbol < SymbolType > variablesBar, const RankedTree < SymbolType > & tree ) : PrefixRankedBarNonlinearPattern ( TreeAuxiliary::computeBars ( tree.getAlphabet ( ), barBase ) + ext::set < common::ranked_symbol < SymbolType > > { variablesBar }, variablesBar, alphabet::WildcardSymbol::instance < common::ranked_symbol < SymbolType > > ( ), { }, tree.getAlphabet ( ) + TreeAuxiliary::computeBars ( tree.getAlphabet ( ), barBase ) + ext::set < common::ranked_symbol < SymbolType > > { variablesBar, alphabet::WildcardSymbol::instance < common::ranked_symbol < SymbolType > > ( ) }, TreeAuxiliary::treeToPrefix ( tree.getContent ( ), alphabet::WildcardSymbol::instance < common::ranked_symbol < SymbolType > > ( ), { }, barBase, variablesBar ) ) {
}

template < class SymbolType >
PrefixRankedBarNonlinearPattern < SymbolType >::PrefixRankedBarNonlinearPattern ( SymbolType barBase, common::ranked_symbol < SymbolType > variablesBar, const RankedPattern < SymbolType > & tree ) : PrefixRankedBarNonlinearPattern ( TreeAuxiliary::computeBars ( tree.getAlphabet ( ), barBase ) + ext::set < common::ranked_symbol < SymbolType > > { variablesBar }, variablesBar, tree.getSubtreeWildcard ( ), { }, tree.getAlphabet ( ) + TreeAuxiliary::computeBars ( tree.getAlphabet ( ), barBase ) + ext::set < common::ranked_symbol < SymbolType > > { variablesBar, tree.getSubtreeWildcard ( ) }, TreeAuxiliary::treeToPrefix ( tree.getContent ( ), tree.getSubtreeWildcard ( ), { }, barBase, variablesBar ) ) {
}

template < class SymbolType >
PrefixRankedBarNonlinearPattern < SymbolType >::PrefixRankedBarNonlinearPattern ( SymbolType barBase, common::ranked_symbol < SymbolType > variablesBar, const RankedNonlinearPattern < SymbolType > & tree ) : PrefixRankedBarNonlinearPattern ( TreeAuxiliary::computeBars ( tree.getAlphabet ( ), barBase ) + ext::set < common::ranked_symbol < SymbolType > > { variablesBar }, variablesBar, tree.getSubtreeWildcard ( ), tree.getNonlinearVariables ( ), tree.getAlphabet ( ) + TreeAuxiliary::computeBars ( tree.getAlphabet ( ), barBase ) + ext::set < common::ranked_symbol < SymbolType > > { variablesBar, tree.getSubtreeWildcard ( ) } + tree.getNonlinearVariables ( ), TreeAuxiliary::treeToPrefix ( tree.getContent ( ), tree.getSubtreeWildcard ( ), tree.getNonlinearVariables ( ), barBase, variablesBar ) ) {
}

template < class SymbolType >
PrefixRankedBarNonlinearPattern < SymbolType >::PrefixRankedBarNonlinearPattern ( const PrefixRankedBarTree < SymbolType > & tree ) : PrefixRankedBarNonlinearPattern ( tree.getBars ( ) + ext::set < common::ranked_symbol < SymbolType > > { alphabet::VariablesBarSymbol::instance < common::ranked_symbol < SymbolType > > ( ) }, alphabet::VariablesBarSymbol::instance < common::ranked_symbol < SymbolType > > ( ), alphabet::WildcardSymbol::instance < common::ranked_symbol < SymbolType > > ( ), { }, tree.getAlphabet ( ) + ext::set < common::ranked_symbol < SymbolType > > { alphabet::VariablesBarSymbol::instance < common::ranked_symbol < SymbolType > > ( ), alphabet::WildcardSymbol::instance < common::ranked_symbol < SymbolType > > ( ) }, tree.getContent ( ) ) {
}

template < class SymbolType >
PrefixRankedBarNonlinearPattern < SymbolType >::PrefixRankedBarNonlinearPattern ( const PrefixRankedBarPattern < SymbolType > & tree ) : PrefixRankedBarNonlinearPattern ( tree.getBars ( ), tree.getVariablesBar ( ), tree.getSubtreeWildcard ( ), { }, tree.getAlphabet ( ), tree.getContent ( ) ) {
}

template < class SymbolType >
PrefixRankedBarNonlinearPattern < SymbolType >::PrefixRankedBarNonlinearPattern ( const RankedTree < SymbolType > & tree ) : PrefixRankedBarNonlinearPattern ( alphabet::BarSymbol::instance < SymbolType > ( ), alphabet::VariablesBarSymbol::instance < common::ranked_symbol < SymbolType > > ( ), tree ) {
}

template < class SymbolType >
PrefixRankedBarNonlinearPattern < SymbolType >::PrefixRankedBarNonlinearPattern ( const RankedPattern < SymbolType > & tree ) : PrefixRankedBarNonlinearPattern ( alphabet::BarSymbol::instance < SymbolType > ( ), alphabet::VariablesBarSymbol::instance < common::ranked_symbol < SymbolType > > ( ), tree ) {
}

template < class SymbolType >
PrefixRankedBarNonlinearPattern < SymbolType >::PrefixRankedBarNonlinearPattern ( const RankedNonlinearPattern < SymbolType > & tree ) : PrefixRankedBarNonlinearPattern ( alphabet::BarSymbol::instance < SymbolType > ( ), alphabet::VariablesBarSymbol::instance < common::ranked_symbol < SymbolType > > ( ), tree ) {
}

template < class SymbolType >
const ext::vector < common::ranked_symbol < SymbolType > > & PrefixRankedBarNonlinearPattern < SymbolType >::getContent ( ) const & {
	return this->m_Data;
}

template < class SymbolType >
ext::vector < common::ranked_symbol < SymbolType > > && PrefixRankedBarNonlinearPattern < SymbolType >::getContent ( ) && {
	return std::move ( this->m_Data );
}

template < class SymbolType >
void PrefixRankedBarNonlinearPattern < SymbolType >::setContent ( ext::vector < common::ranked_symbol < SymbolType > > data ) {
	arityChecksum ( data );

	ext::set < common::ranked_symbol < SymbolType > > minimalAlphabet ( data.begin ( ), data.end ( ) );
	ext::set < common::ranked_symbol < SymbolType > > unknownSymbols;
	std::set_difference ( minimalAlphabet.begin ( ), minimalAlphabet.end ( ), getAlphabet ( ).begin ( ), getAlphabet ( ).end ( ), std::inserter ( unknownSymbols, unknownSymbols.end ( ) ) );

	if ( !unknownSymbols.empty ( ) )
		throw TreeException ( "Input symbols not in the alphabet." );

	this->m_Data = std::move ( data );
}

template < class SymbolType >
void PrefixRankedBarNonlinearPattern < SymbolType >::arityChecksum ( const ext::vector < common::ranked_symbol < SymbolType > > & data ) {
	int arityChecksumTerminals = 1;
	int arityChecksumBars = 1;
	int arityChecksumTypes = 0;

	for ( const common::ranked_symbol < SymbolType > & symbol : data ) {
		if ( getBars ( ).count ( symbol ) || ( symbol == getVariablesBar ( ) ) ) {
			arityChecksumBars += ( unsigned ) symbol.getRank ( );
			arityChecksumBars -= 1;
			arityChecksumTypes -= 1;
		} else {
			arityChecksumTerminals += ( unsigned ) symbol.getRank ( );
			arityChecksumTerminals -= 1;
			arityChecksumTypes += 1;
		}
	}

	if ( ( arityChecksumTerminals != 0 ) || ( arityChecksumBars != 0 ) || ( arityChecksumTypes != 0 ) ) throw TreeException ( "The string does not form a tree" );

	for ( unsigned i = 1; i < data.size ( ); ++i )
		if ( ( data[i - 1] == getSubtreeWildcard ( ) ) && ( data[i] != getVariablesBar ( ) ) )
			throw TreeException ( "Inconsystency of SubtreeWildcard and variablesBar" );

	for ( unsigned i = 1; i < data.size ( ); ++i )
		if ( ( getNonlinearVariables ( ).count ( data[i - 1] ) ) && ( data[i] != getVariablesBar ( ) ) )
			throw TreeException ( "Inconsystency of NonlinearVariables and variablesBar" );

}

template < class SymbolType >
bool PrefixRankedBarNonlinearPattern < SymbolType >::isEmpty ( ) const {
	return this->m_Data.empty ( );
}

template < class SymbolType >
int PrefixRankedBarNonlinearPattern < SymbolType >::compare ( const PrefixRankedBarNonlinearPattern & other ) const {
	auto first = ext::tie ( m_Data, getAlphabet ( ), getSubtreeWildcard ( ), getNonlinearVariables ( ), getBars ( ), getVariablesBar ( ) );
	auto second = ext::tie ( other.m_Data, other.getAlphabet ( ), other.getSubtreeWildcard ( ), other.getNonlinearVariables ( ), other.getBars ( ), other.getVariablesBar ( ) );

	static ext::compare < decltype ( first ) > comp;

	return comp ( first, second );
}

template < class SymbolType >
PrefixRankedBarNonlinearPattern < SymbolType >::operator std::string ( ) const {
	std::stringstream ss;
	ss << "\"";

	for ( const common::ranked_symbol < SymbolType > & symbol : this->m_Data )
		ss << symbol;

	ss << "\"";
	return std::move ( ss ).str ( );
}

} /* namespace tree */

namespace core {

/**
 * Helper class specifying constraints for the pattern's internal alphabet component.
 *
 * \tparam SymbolType used for the symbol part of the ranked symbols of the alphabet of the pattern.
 */
template < class SymbolType >
class SetConstraint< tree::PrefixRankedBarNonlinearPattern < SymbolType >, common::ranked_symbol < SymbolType >, tree::GeneralAlphabet > {
public:
	/**
	 * Returns true if the symbol is still used in the pattern.
	 *
	 * \param pattern the tested pattern
	 * \param symbol the tested symbol
	 *
	 * \returns true if the symbol is used, false othervise
	 */
	static bool used ( const tree::PrefixRankedBarNonlinearPattern < SymbolType > & pattern, const common::ranked_symbol < SymbolType > & symbol ) {
		const ext::vector < common::ranked_symbol < SymbolType > > & content = pattern.getContent ( );

		return std::find ( content.begin ( ), content.end ( ), symbol ) != content.end ( ) || pattern.template accessComponent < tree::VariablesBarSymbol > ( ).get ( ) == symbol || pattern.template accessComponent < tree::BarSymbols > ( ).get ( ).count ( symbol ) || pattern.template accessComponent < tree::SubtreeWildcard > ( ).get ( ) == symbol;
	}

	/**
	 * Returns true as all symbols are possibly available to be in an alphabet.
	 *
	 * \param pattern the tested pattern
	 * \param symbol the tested symbol
	 *
	 * \returns true
	 */
	static bool available ( const tree::PrefixRankedBarNonlinearPattern < SymbolType > &, const common::ranked_symbol < SymbolType > & ) {
		return true;
	}

	/**
	 * All symbols are valid as symbols of an alphabet.
	 *
	 * \param pattern the tested pattern
	 * \param symbol the tested symbol
	 */
	static void valid ( const tree::PrefixRankedBarNonlinearPattern < SymbolType > &, const common::ranked_symbol < SymbolType > & ) {
	}
};

/**
 * Helper class specifying constraints for the pattern's internal bar set component.
 *
 * \tparam SymbolType used for the symbol part of the ranked symbols of the alphabet of the pattern.
 */
template < class SymbolType >
class SetConstraint< tree::PrefixRankedBarNonlinearPattern < SymbolType >, common::ranked_symbol < SymbolType >, tree::BarSymbols > {
public:
	/**
	 * Returns true if the symbol is still used in the pattern.
	 *
	 * \param pattern the tested pattern
	 * \param symbol the tested symbol
	 *
	 * \returns true if the symbol is used, false othervise
	 */
	static bool used ( const tree::PrefixRankedBarNonlinearPattern < SymbolType > & pattern, const common::ranked_symbol < SymbolType > & symbol ) {
		const ext::vector < common::ranked_symbol < SymbolType > > & content = pattern.getContent ( );

		return std::find ( content.begin ( ), content.end ( ), symbol ) != content.end ( ) || pattern.template accessComponent < tree::VariablesBarSymbol > ( ).get ( ) == symbol;
	}

	/**
	 * Determines whether the symbol is available in the pattern's alphabet.
	 *
	 * \param pattern the tested pattern
	 * \param symbol the tested symbol
	 *
	 * \returns true if the symbol is already in the alphabet of the pattern
	 */
	static bool available ( const tree::PrefixRankedBarNonlinearPattern < SymbolType > & pattern, const common::ranked_symbol < SymbolType > & symbol ) {
		return pattern.template accessComponent < tree::GeneralAlphabet > ( ).get ( ).count ( symbol );
	}

	/**
	 * All symbols are valid as a bar symbol of the pattern.
	 *
	 * \param pattern the tested pattern
	 * \param symbol the tested symbol
	 */
	static void valid ( const tree::PrefixRankedBarNonlinearPattern < SymbolType > &, const common::ranked_symbol < SymbolType > & ) {
	}
};

/**
 * Helper class specifying constraints for the pattern's internal nonlinear variables component.
 *
 * \tparam SymbolType used for the symbol part of the ranked symbols of the alphabet of the pattern.
 */
template < class SymbolType >
class SetConstraint< tree::PrefixRankedBarNonlinearPattern < SymbolType >, common::ranked_symbol < SymbolType >, tree::NonlinearAlphabet > {
public:
	/**
	 * Returns false. Nonlinear symbol is only a mark that the pattern itself does require further. //FIXME it is however followed by variables bar... Maybe get rid of the variables bar?
	 *
	 * \param pattern the tested pattern
	 * \param symbol the tested symbol
	 *
	 * \returns true if the symbol is used, false othervise
	 */
	static bool used ( const tree::PrefixRankedBarNonlinearPattern < SymbolType > &, const common::ranked_symbol < SymbolType > & ) {
		return false;
	}

	/**
	 * Determines whether the symbol is available in the pattern's alphabet.
	 *
	 * \param pattern the tested pattern
	 * \param symbol the tested symbol
	 *
	 * \returns true
	 */
	static bool available ( const tree::PrefixRankedBarNonlinearPattern < SymbolType > & pattern, const common::ranked_symbol < SymbolType > & symbol ) {
		return pattern.template accessComponent < tree::GeneralAlphabet > ( ).get ( ).count ( symbol );
	}

	/**
	 * Nonlinear variable needs to have zero arity and needs to be different from subtree wildcard.
	 *
	 * \param pattern the tested pattern
	 * \param symbol the tested symbol
	 *
	 * \throws TreeException if the symbol does not have zero arity
	 */
	static void valid ( const tree::PrefixRankedBarNonlinearPattern < SymbolType > & pattern, const common::ranked_symbol < SymbolType > & symbol) {
		if ( ( unsigned ) symbol.getRank ( ) != 0 )
			throw tree::TreeException ( "Nonlinear variable has nonzero arity" );

		if ( pattern.template accessComponent < tree::SubtreeWildcard > ( ).get ( ) == symbol )
			throw tree::TreeException ( "Symbol " + ext::to_string ( symbol ) + "cannot be set as nonlinear variable since it is already subtree wildcard" );
	}
};

/**
 * Helper class specifying constraints for the pattern's internal subtree wildcard element.
 *
 * \tparam SymbolType used for the symbol part of the ranked symbols of the alphabet of the pattern.
 */
template < class SymbolType >
class ElementConstraint< tree::PrefixRankedBarNonlinearPattern < SymbolType >, common::ranked_symbol < SymbolType >, tree::SubtreeWildcard > {
public:
	/**
	 * Determines whether the symbol is available in the pattern's alphabet.
	 *
	 * \param pattern the tested pattern
	 * \param symbol the tested symbol
	 *
	 * \returns true if the symbol is already in the alphabet of the pattern
	 */
	static bool available ( const tree::PrefixRankedBarNonlinearPattern < SymbolType > & pattern, const common::ranked_symbol < SymbolType > & symbol ) {
		return pattern.template accessComponent < tree::GeneralAlphabet > ( ).get ( ).count ( symbol );
	}

	/**
	 * Subtree wildcard needs to have zero arity and it needs to be different from any nonlinear variable of the tree.
	 *
	 * \param pattern the tested pattern
	 * \param symbol the tested symbol
	 *
	 * \throws TreeException if the symbol does not have zero arity
	 */
	static void valid ( const tree::PrefixRankedBarNonlinearPattern < SymbolType > & pattern, const common::ranked_symbol < SymbolType > & symbol) {
		if ( ( unsigned ) symbol.getRank ( ) != 0 )
			throw tree::TreeException ( "SubtreeWildcard symbol has nonzero arity" );

		if ( pattern.template accessComponent < tree::NonlinearAlphabet > ( ).get ( ).count ( symbol ) )
			throw tree::TreeException ( "Symbol " + ext::to_string ( symbol ) + "cannot be set as subtree wildcard since it is already nonlinear variable" );
	}
};

/**
 * Helper class specifying constraints for the pattern's internal variables bar element.
 *
 * \tparam SymbolType used for the symbol part of the ranked symbols of the alphabet of the pattern.
 */
template < class SymbolType >
class ElementConstraint< tree::PrefixRankedBarNonlinearPattern < SymbolType >, common::ranked_symbol < SymbolType >, tree::VariablesBarSymbol > {
public:
	/**
	 * Determines whether the symbol is available in the pattern's alphabet.
	 *
	 * \param pattern the tested pattern
	 * \param symbol the tested symbol
	 *
	 * \returns true if the symbol is already in the alphabet of the pattern
	 */
	static bool available ( const tree::PrefixRankedBarNonlinearPattern < SymbolType > & pattern, const common::ranked_symbol < SymbolType > & symbol ) {
		return pattern.template accessComponent < tree::BarSymbols > ( ).get ( ).count ( symbol );
	}

	/**
	 * Variables bar needs to have zero arity.
	 *
	 * \param pattern the tested pattern
	 * \param symbol the tested symbol
	 *
	 * \throws TreeException if the symbol does not have zero arity
	 */
	static void valid ( const tree::PrefixRankedBarNonlinearPattern < SymbolType > &, const common::ranked_symbol < SymbolType > & symbol) {
		if ( ( unsigned ) symbol.getRank ( ) != 0 )
			throw tree::TreeException ( "VariablesBarSymbol has nonzero arity" );
	}
};

/**
 * Helper for normalisation of types specified by templates used as internal datatypes of symbols.
 *
 * \returns new instance of the tree with default template parameters or unmodified instance if the template parameters were already default ones
 */
template < class SymbolType >
struct normalize < tree::PrefixRankedBarNonlinearPattern < SymbolType > > {
	static tree::PrefixRankedBarNonlinearPattern < > eval ( tree::PrefixRankedBarNonlinearPattern < SymbolType > && value ) {
		common::ranked_symbol < DefaultSymbolType > variablesBars = alphabet::SymbolNormalize::normalizeRankedSymbol ( std::move ( value ).getVariablesBar ( ) );
		common::ranked_symbol < DefaultSymbolType > wildcard = alphabet::SymbolNormalize::normalizeRankedSymbol ( std::move ( value ).getSubtreeWildcard ( ) );
		ext::set < common::ranked_symbol < DefaultSymbolType > > nonlinearAlphabet = alphabet::SymbolNormalize::normalizeRankedAlphabet ( std::move ( value ).getNonlinearVariables ( ) );
		ext::set < common::ranked_symbol < DefaultSymbolType > > bars = alphabet::SymbolNormalize::normalizeRankedAlphabet ( std::move ( value ).getBars ( ) );
		ext::set < common::ranked_symbol < DefaultSymbolType > > alphabet = alphabet::SymbolNormalize::normalizeRankedAlphabet ( std::move ( value ).getAlphabet ( ) );
		ext::vector < common::ranked_symbol < DefaultSymbolType > > content = alphabet::SymbolNormalize::normalizeRankedSymbols ( std::move ( value ).getContent ( ) );

		return tree::PrefixRankedBarNonlinearPattern < > ( std::move ( bars ), std::move ( variablesBars ), std::move ( wildcard ), std::move ( nonlinearAlphabet ), std::move ( alphabet ), std::move ( content ) );
	}
};

} /* namespace core */

extern template class tree::PrefixRankedBarNonlinearPattern < >;

#endif /* PREFIX_RANKED_BAR_NONLINEAR_PATTERN_H_ */
