/*******************************************************************************
 * Copyright 2008, 2009, 2014 Institute of Mathematics and Computer Science, University of Latvia
 * Author: Pēteris Paikens
 *
 *     This program 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.
 *
 *     This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package lv.semti.morphology.lexicon;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;

import org.w3c.dom.DOMException;
import org.w3c.dom.Node;

import lv.semti.morphology.attributes.*;

/**
 * Satur informāciju par vienu galotni (jeb locīšanas paradigmu)
 *
 * @author Pēteris Paikens
 *
 */
public class Ending extends AttributeValues {
	private int id;			  // numurs pēc kārtas - ID
	private String ending;	  // Pati galotne
	private int mija;		  // kura mija jāpielieto saknei, lai šo galotni tai pieliktu
							  // FIXME - varbūt kādu sasaisti ar miju objektu šeit?

	public int stemID = 1; // kurai no (potenciāli 3) leksēmas saknēm galotne atbilst - darbībasvārdiem tas ir aktuāli
	//FIXME - stemNr vietām numurējas no 1 vietām no 0 - ļoti bīstami!
	private Paradigm paradigm;
	private Ending lemmaEnding = null;

	public Ending () {
		//irok
	}

	public Ending(Paradigm paradigm, Node node) {
		super(node);
		this.paradigm = paradigm;

		if (!node.getNodeName().equalsIgnoreCase("Ending")) throw new Error("Node '" + node.getNodeName() + "' but Ending expected.");

		Node n = node.getAttributes().getNamedItem("ID");
		if (n != null)
			this.setID(Integer.parseInt(n.getTextContent()));

		n = node.getAttributes().getNamedItem("StemChange");
		if (n != null)
			this.setMija(Integer.parseInt(n.getTextContent()));

		n = node.getAttributes().getNamedItem("Ending");
		if (n != null)
			this.setEnding(n.getTextContent());

		n = node.getAttributes().getNamedItem("StemID");
		if (n != null)
			this.stemID = Integer.parseInt(n.getTextContent());

		n = node.getAttributes().getNamedItem("LemmaEnding");
		if (n != null)
			try {
				setLemmaEnding(Integer.parseInt(n.getTextContent()));
				//FIXME - nestrādās, ja pamatformas galotne tiks ielasīta pēc šīs galotnes, nevis pirms..
			} catch (NumberFormatException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (DOMException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (Exception e) {
				throw new Error(e.getMessage());
			}
	}

	@Override
	public void toXML (Writer pipe) throws IOException {
		pipe.write("<Ending");
		pipe.write(" ID=\""+String.valueOf(id)+"\"");
		pipe.write(" StemChange=\""+String.valueOf(mija)+"\"");
		pipe.write(" Ending=\""+ending+"\"");
		pipe.write(" StemID=\""+String.valueOf(stemID)+"\"");
		if (lemmaEnding != null)
			pipe.write(" LemmaEnding=\""+String.valueOf(lemmaEnding.id)+"\"");
		pipe.write(">");

		super.toXML(pipe); // Īpašības UzXML
		pipe.write("</Ending>\n");
	}

	public int getID() {
		return id;
	}

	public void setID(int nr) {
		this.id = nr;
	}

	public int getMija() {
		return mija;
	}

	public void setMija(int mija) {
		this.mija = mija;
	}

	public String getEnding() {
		return ending;
	}

	public void setEnding(String ending) {
		this.ending = ending;
	}

	public class WrongEndingException extends Exception {
		public WrongEndingException(String message) {
			super(message);
		}
	}
	// tiek pieņemts, ka izsaucošā funkcija nodrošina, ka vārds tiešām beidzas ar šo galotni.
	public String stem (String word) throws WrongEndingException {
		if (!word.endsWith(ending))
			throw new WrongEndingException("Gļuks - vārds (" + word + ") nebeidzas ar norādīto galotni (" + ending + ")");
		return word.substring(0, word.length()- ending.length());
	}

	public Ending getLemmaEnding() {
		if (this.lemmaEnding == null)
			return this.paradigm.getLemmaEnding();
		return lemmaEnding;
	}

	public void setLemmaEnding(int lemmaEndingNr){
		if (lemmaEndingNr == id) lemmaEnding = this;
			// vajag, jo šai gadījumā pati pamatformas galotne vēl nav vārdgrupā, un vārdgrupa.galotnePēcNr būs null.
		else lemmaEnding = paradigm.endingByNr( lemmaEndingNr );
	}

	public Paradigm getParadigm() {
		return paradigm;
	}

	protected void setParadigm(Paradigm paradigm) {
		this.paradigm = paradigm;
		//FIXME - būtu jālikvidē un jāpārceļ tīri uz konstruktoru
	}

	/*
	 * Returned Lexemes shouldn't be modified to avoid changing recognition of other words!
	 * Not cloned due to performance and memory usage concerns.
	 */
	public ArrayList<Lexeme> getEndingLexemes(String celms) {
		return paradigm.getLexemesByStem().get(stemID-1).get(celms);
	}
}


/*******************************************************************************
 * Copyright 2008, 2009, 2014 Institute of Mathematics and Computer Science, University of Latvia
 * Author: Pēteris Paikens
 *
 *     This program 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.
 *
 *     This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package lv.semti.morphology.corpus;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map.Entry;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import lv.semti.morphology.attributes.AttributeNames;
import lv.semti.morphology.attributes.AttributeValues;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * This class handles frequency statistics that assess the more probable
 * analysis variant.
 */
public class Statistics {

	/**
	 * Default filename for statistics file.
	 */
	public final static String DEFAULT_STATISTICS_FILE = "Statistics.xml";
	public double lexemeWeight = 1000; //How much lexeme count should be weighed as a multiple of ending count

	/**
	 * Lexeme frequencies, indexed by lexeme IDs.
	 */
	public HashMap<Integer, Integer> lexemeFrequency = new HashMap<Integer, Integer>();
	/**
	 * Ending frequencies, indexed by ending IDs.
	 */
	public HashMap<Integer, Integer> endingFrequency = new HashMap<Integer, Integer>();

	/**
	 * Add one occurrence of one lexeme.
	 * @param lexemeId	lexeme identifier.
	 */
	public void addLexeme(int lexemeId) {
		int count = 1;
		if (lexemeFrequency.get(lexemeId) != null)
			count = lexemeFrequency.get(lexemeId) + 1;
		lexemeFrequency.put(lexemeId, count);
	}
	/**
	 * Add one occurrence of one ending.
	 * @param endingId	ending identifier.
	 */
	public void addEnding(int endingId) {
		int count = 1;
		if (endingFrequency.get(endingId) != null)
			count = endingFrequency.get(endingId) + 1;
		endingFrequency.put(endingId, count);
	}

	/**
	 * Convert frequency data in XML format.
	 * @param stream	output stream.
	 */
	public void toXML (Writer stream)
	throws IOException {
		stream.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
		stream.write("<Statistika>\n");
		stream.write("<Galotņu_biežums\n");
		for (Entry<Integer,Integer> tuple : endingFrequency.entrySet()) {
			stream.write(" Galotne_"+tuple.getKey().toString()+"=\""+tuple.getValue().toString()+"\"");
		}
		stream.write("/>\n");

		stream.write("<Leksēmu_biežums\n");
		for (Entry<Integer,Integer> tuple : lexemeFrequency.entrySet()) {
			stream.write(" Leksēma_"+tuple.getKey().toString()+"=\""+tuple.getValue().toString()+"\"");
		}
		stream.write("/>\n");
		stream.write("</Statistika>\n");
		stream.flush();
	}

	private static Statistics singleton;

	public static Statistics getStatistics() {
		if (singleton == null)
			try {
			    singleton = new Statistics(DEFAULT_STATISTICS_FILE);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                singleton = new Statistics();
            }
		return singleton;
	}

	public static Statistics getStatistics(String fileName) {
		if (singleton == null)
			try {
				singleton = new Statistics(fileName);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
                singleton = new Statistics();
			}
		return singleton;
	}

	/**
	 * Create empty statistics object.
	 */
	public Statistics() {
		// var arī bez nekā
	}

	/**
	 * Create statistics object from XML file.
	 * @param fileName	input file.
	 */
	private Statistics(String fileName)
	throws SAXException, IOException, ParserConfigurationException {

		Document doc = null;

		InputStream stream = this.getClass().getClassLoader().getResourceAsStream(fileName);
		DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		doc = docBuilder.parse(stream);

		Node node = doc.getDocumentElement();
		if (!node.getNodeName().equalsIgnoreCase("Statistika"))
			throw new Error("Node " + node.getNodeName() + " nav Statistika!");

		NodeList nodes = node.getChildNodes();
		for (int i = 0; i < nodes.getLength(); i++) {
			if (nodes.item(i).getNodeName().equals("Galotņu_biežums"))
				for (int j = 0; j < nodes.item(i).getAttributes().getLength(); j++) {
					Node n = nodes.item(i).getAttributes().item(j);
					int endingId = Integer.parseInt(n.getNodeName().substring(n.getNodeName().indexOf('_')+1));
					int count = Integer.parseInt(n.getTextContent());
					endingFrequency.put(endingId, count);
				}
			if (nodes.item(i).getNodeName().equals("Leksēmu_biežums"))
				for (int j = 0; j < nodes.item(i).getAttributes().getLength(); j++) {
					Node n = nodes.item(i).getAttributes().item(j);
					int lexemeId = Integer.parseInt(n.getNodeName().substring(n.getNodeName().indexOf('_')+1));
					int count = Integer.parseInt(n.getTextContent());
					lexemeFrequency.put(lexemeId, count);
				}
		}
	}

	/**
	 * Cumulative frequency estimate for given wordform.
	 * @param wordform	wordform to describe.
	 * @return			lexeme frequency + ending frequency.
	 */
	public double getEstimate(AttributeValues wordform) {
		double estimate = 0.1;
		String endingIdStr = wordform.getValue(AttributeNames.i_EndingID);
		int endingId = (endingIdStr == null) ? -1 : Integer.parseInt(endingIdStr);
		if (endingFrequency.get(endingId) != null) estimate += endingFrequency.get(endingId);

		String lexemeIdStr = wordform.getValue(AttributeNames.i_LexemeID);
		int lexemeId = (lexemeIdStr == null) ? -1 : Integer.parseInt(lexemeIdStr);
		if (lexemeFrequency.get(lexemeId) != null) estimate += lexemeFrequency.get(lexemeId) * lexemeWeight;

		return estimate;
	}

}


/*******************************************************************************
 * Copyright 2008, 2009, 2014 Institute of Mathematics and Computer Science, University of Latvia
 * Author: Pēteris Paikens, Imants Borodkins
 *
 *     This program 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.
 *
 *     This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package lv.semti.morphology.analyzer;

import java.util.LinkedList;
import java.util.List;

import lv.semti.morphology.attributes.AttributeNames;
import org.apache.commons.lang3.StringUtils;

/**
 * Tools for detecting chunk and token bounds.
 * When you edit this, please, update tokenize.pl in Chunker, too!
 */
public class Splitting {
	// Vārdā, atdalītājā, atstarpē
	private enum Status {IN_WORD, IN_SPACE}; // , IN_DELIMITER, IN_EXCEPTION - tagad šo funkcionalitāti dara Trie morphoAnalyzer.automats

	public static int DEFAULT_SENTENCE_LENGTH_CAP = 250;

	/**
	 * Determine, if given word should split a chunk (ends a sentence, like a period or exclamation mark)
	 */
	public static boolean isChunkCloser(Word word) {
		return word.hasAttribute(AttributeNames.i_PieturziimesTips, AttributeNames.v_Punkts); // pieņemam, ka tikai 'zs' tags ir teikuma beigas - tur ir punkts, jautājumzīme, izsaukumzīme, daudzpunkte un to kombinācijas/variācijas.
	}

	public static boolean isSeparator(char c)
	{
		String separators=" \t\n\r\u00A0\u2029\u200B.?:/!,;\"'`´(){}<>«»-+[]—‐‑‒–―‘’‚‛“”„‟′″‴‵‶‷‹›‼‽⁈⁉․‥…&•*";
		return separators.contains(String.valueOf(c));
	}

	/**
	 * Determine if given char is a whitespace char (space, tab, newline).
	 */
	public static boolean isSpace(char c)
	{
	    return Character.isWhitespace(c) || Character.isISOControl(c) || c == '\u00A0' || c == '\uFEFF' || c == '\u2029' || c == '\u200B';
	}

	private static Word formToken(Analyzer morphoAnalyzer, String str, int start, int end, StringBuilder accumulatedWhitespace) {
	    String word = str.substring(start, end);
	    word = word.replace("\u00AD", ""); // Soft hyphen gets removed from word before analysis
        Word token = (morphoAnalyzer == null) ? new Word(word) : morphoAnalyzer.analyze(word);

        String whitespace = accumulatedWhitespace.toString().replace("\u200B", ""); // zero-width spaces are used as temporary separators
        int offset = start - StringUtils.countMatches(str.substring(0,start), '\u200B');
        for (Wordform wf : token.wordforms) {
            wf.addAttribute(AttributeNames.i_WhitespaceBefore, whitespace);
            wf.addAttribute(AttributeNames.i_Offset, Integer.toString(offset));
        }
        return token;
    }

	/*
	 * Tokenizes the string (sentence?) and runs morphoanalysis on each word.
	 */
	public static LinkedList<Word> tokenize(Analyzer morphoAnalyzer, String chunk) {
		LinkedList<Word> tokens = new LinkedList<Word>();
		if (chunk == null) return tokens;

		Trie automats = morphoAnalyzer.automats;

	    //bug fix - pievienota beigās whitespace
		String str = chunk+" ";
		//workaround dubultapostrofu izvirtībai
        str = str.replaceAll("''", "\u200B''"); // FIXME mēs te mazliet izčakarējam accumulatedWhitespace on Offsetus
        //workaround teikuma beigu saīsinājumiem utt
        str = str.replaceAll("([\\p{L}\\d])\\.(\\p{Z})*$", "$1\u200B.$2"); // FIXME mēs te mazliet izčakarējam accumulatedWhitespace un offsetus
//        str = str.replaceAll("([\\d])\\.(\\p{Z})*$", "$1\u200B.$2"); // FIXME mēs te mazliet izčakarējam accumulatedWhitespace un offsetus

        // te tiek ciklā doti visi tekstā esošie vārdi uz morfoanalīzi.
        int progress = 0;
		boolean inApostrophes=false;
		Status statuss = Status.IN_SPACE;
		StringBuilder accumulatedWhitespace = new StringBuilder();
		int lastGoodEnd=0;
		boolean canEndInNextStep=false;

		for (int i = 0; i < str.length(); i++) {
			switch (statuss) {
			case IN_SPACE:
				if (!Splitting.isSpace(str.charAt(i))) {
					if (str.charAt(i)=='\'') inApostrophes=true;

					automats.reset(); //atjauno automāta stāvokli
					automats.findNextBranch(str.charAt(i)); //atrod pirmo derīgo zaru

					if(automats.status()>0) { //pārbauda vai automātā atrada meklēto simbolu
						//ja atrada
						statuss=Status.IN_WORD;
						progress=i;
						//pārbauda vai ar to var arī virkne beigties
						canEndInNextStep = (automats.status()==2);
					} else {
						//ja neatrada, pievieno vienu simbolu un mēģina vēl
                        tokens.add( formToken(morphoAnalyzer, str, i, i+1, accumulatedWhitespace));
					}
				} else {
				   accumulatedWhitespace.append(str.charAt(i));
                }
				break;
			case IN_WORD:
				//pārbauda vai ir atrastas potenciālās beigas
		        if (canEndInNextStep==true &&
			            (Splitting.isSeparator(str.charAt(i)) || !Character.isLetter((i>0 ? str.charAt(i-1) : 0) ) ) )
				{
					lastGoodEnd=i;
					if(str.charAt(i)=='\'' && inApostrophes) {
						tokens.add( formToken(morphoAnalyzer, str, progress, i, accumulatedWhitespace));
                        accumulatedWhitespace = new StringBuilder();
                        tokens.add( formToken(morphoAnalyzer, str, i, i+1, accumulatedWhitespace));
						inApostrophes=false;
						statuss=Status.IN_SPACE;
						break;
					}
				}
				canEndInNextStep=false;

				//mēģina atrast nākamo simbolu automātā
				if (automats.findNext(str.charAt(i))>0) { //ja atrada
					//pārbauda vai ar to var arī virkne beigties
					if (automats.status()==2)
						canEndInNextStep=true;
				} else {
					//ja neatrada, pārbauda vai automāta darbības laikā tika atrasta potenciālā beigu pozīcija
					if (lastGoodEnd>progress) {
                        tokens.add( formToken(morphoAnalyzer, str, progress, lastGoodEnd, accumulatedWhitespace));
						i=lastGoodEnd-1;
						statuss = Status.IN_SPACE;
                        accumulatedWhitespace = new StringBuilder();
					} else {
						i=progress;
						//mēgina atrast nākamo derīgo zaru
						automats.nextBranch();
						automats.findNextBranch(str.charAt(i));
						if(automats.status()>0) { //pārbauda vai atrada meklēto simbolu
							//pārbauda vai ar to var arī virkne beigties
							if(automats.status()==2)
								canEndInNextStep=true;
						} else {
							//ja neatrada, pievieno simbolu rezultātam un pēc tam dosies meklēt jauno sākumu
                            //vispār šis ir fishy. FIXME
                            tokens.add( formToken(morphoAnalyzer, str, i,i+1, accumulatedWhitespace));
							statuss = Status.IN_SPACE;
                            accumulatedWhitespace = new StringBuilder();
						}
					}
				}
				break;
			}
		} // for i..

		if (statuss == Status.IN_WORD) {
			tokens.add( formToken(morphoAnalyzer, str, progress, str.length(), accumulatedWhitespace));
		}

		return tokens;
	}

	/***
	 * Tokenizes some text (usually a sentence)
	 * @param morphoAnalyzer
	 * @param chunk
	 * @param bruteSplit
	 * @return
	 */
	public static LinkedList<Word> tokenize(Analyzer morphoAnalyzer, String chunk, boolean bruteSplit) {
		if(bruteSplit)
		{
			LinkedList<Word> tokens = new LinkedList<Word>();
			if (chunk == null) return tokens;
			String[] parts_of_string = chunk.trim().split(" ");
			for(String part : parts_of_string)
			{
				if (part.length()>0)
					tokens.add( (morphoAnalyzer == null) ?
						new Word(part) :
						morphoAnalyzer.analyze(part));
			}
			return tokens;
		}
		else
		{
			return tokenize(morphoAnalyzer, chunk);
		}
	}

	public static LinkedList<LinkedList<Word>> tokenizeSentences(
			Analyzer morphoAnalyzer, String paragraph) {
		return tokenizeSentences(morphoAnalyzer, paragraph, DEFAULT_SENTENCE_LENGTH_CAP);
	}
	/***
	 * Tokenizes a paragraph, and splits it into sentences.
	 * @param morphoAnalyzer
	 * @param paragraph
	 * @return
	 */
	public static LinkedList<LinkedList<Word>> tokenizeSentences(
		 	Analyzer morphoAnalyzer, String paragraph, int lengthCap) {
		LinkedList<LinkedList<Word>> result = new LinkedList<LinkedList<Word>>();

		List<Word> tokens = Splitting.tokenize(morphoAnalyzer, paragraph);
		LinkedList<Word> sentence = new LinkedList<Word>();
		for (Word word : tokens) {
		    // Teikumu beigas iekšā tiešajā runā - pievelkam pēdiņu klāt
            if (sentence.size() == 0) {
                if ((word.isRecognized() && word.getBestWordform().getTag().equalsIgnoreCase("zq")) || word.getToken().equals(")")) {
                    // Pārbaudam vai iepriekšējā teikuma beigās ir punkts
                    if (!result.isEmpty() && !result.getLast().isEmpty()) {
                        String prevtoken = result.getLast().getLast().getToken();
                        if (prevtoken.equals(".") || prevtoken.equals("!") || prevtoken.equals("?") || prevtoken.equals("\"")) {
                            result.getLast().add(word);
                            continue;
                        }
                    }
                }
            }

			sentence.add(word);
			if ( Splitting.isChunkCloser(word) || // does this token look like end of sentence
				(sentence.size() >= lengthCap-5 && (word.hasAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Punctuation) || word.getToken().startsWith("<")) )
				|| sentence.size() > lengthCap) { 		// hard limit
				result.add(sentence);
				sentence = new LinkedList<Word>();
			}
		}

		if (!sentence.isEmpty())
			result.add(sentence);
		return result;
	}

}


/*******************************************************************************
 * Copyright 2008, 2009, 2014 Institute of Mathematics and Computer Science, University of Latvia
 * Author: Pēteris Paikens
 *
 *     This program 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.
 *
 *     This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package lv.semti.morphology.analyzer;

import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.Writer;
import java.util.ArrayList;

import org.w3c.dom.Node;

import lv.semti.morphology.attributes.AttributeNames;
import lv.semti.morphology.attributes.AttributeValues;
import lv.semti.morphology.lexicon.*;

/**
 * One morphological analysis variant for a word or token.
 *
 * @author Pēteris
 */
public class Wordform extends AttributeValues implements Serializable{

	private static final long serialVersionUID = 1L;
	private String token;
	private transient Ending ending;
	public transient Lexeme lexeme;

	public Wordform (String token, Lexeme lexeme, Ending ending) {
	    this(token, lexeme, ending, null);
	}

	public Wordform(String token, Lexeme lexeme, Ending ending, String originalWord) {
		this.token = token;
		this.lexeme = lexeme;
		this.ending = ending;
		Paradigm paradigm = ending.getParadigm();

		addAttribute(AttributeNames.i_Word, token);
		addAttribute(AttributeNames.i_Mija, Integer.toString(ending.getMija()));
		addAttributes(paradigm);
		addAttributes(ending);
		addAttribute(AttributeNames.i_EndingID, Integer.toString(ending.getID()));
		addAttribute(AttributeNames.i_ParadigmID, Integer.toString(paradigm.getID()));

		Boolean fixed_stem;
		if (lexeme != null) {
			addAttributes(lexeme);
			addAttribute(AttributeNames.i_SourceLemma, lexeme.getValue(AttributeNames.i_Lemma));  //TODO - šis teorētiski varētu aizstāt visus pārējos SourceLemma pieminējumus (citus varbūt var dzēst)
			addAttribute(AttributeNames.i_LexemeID, Integer.toString(lexeme.getID()));
			fixed_stem = lexeme.isMatchingStrong(AttributeNames.i_NumberSpecial, AttributeNames.v_PlurareTantum)  ||
						 lexeme.isMatchingStrong(AttributeNames.i_NumberSpecial, AttributeNames.v_SingulareTantum) ||
						 lexeme.isMatchingStrong(AttributeNames.i_Declension, AttributeNames.v_InflexibleGenitive);
			// || leksēma.isMatchingStrong(AttributeNames.i_Deminutive, "-iņ-")
		} else fixed_stem = true;

		Ending lemmaEnding = ending.getLemmaEnding();
		// FIXME šis 'if' būtu jāsaprot un jāsakārto - lai ir sakarīgi, bet nesalauž specgadījumus ('vairāk' -> pamatforma 'daudz' utml)
		if (lemmaEnding != null && !(paradigm.getID() == 25 || paradigm.getID() == 29 || paradigm.getID() == 21)
				&& !fixed_stem) {
			String thirdStem = null;
			if (paradigm.getStems() == 3) thirdStem = lexeme.getStem(2);
			String stem = lexeme.getStem(lemmaEnding.stemID-1);
			ArrayList<Variants> celmi = Mijas.MijasLocīšanai(stem, lemmaEnding.getMija(), thirdStem, false, this.isMatchingStrong(AttributeNames.i_NounType, AttributeNames.v_ProperNoun));

			if (celmi.size()>0) stem = celmi.get(0).celms; // FIXME - nav objektīva pamata ņemt tieši pirmo, netīri

			String lemma = stem + lemmaEnding.getEnding();
			if (lexeme.isMatchingStrong(AttributeNames.i_NounType, AttributeNames.v_ProperNoun)) {
				lemma = Character.toUpperCase(lemma.charAt(0)) + lemma.substring(1);
			}
			String originalLemma = lexeme.getValue(AttributeNames.i_Lemma);
            lemma = Lexicon.recapitalize(lemma, originalLemma);
			addAttribute(AttributeNames.i_Lemma, lemma );
			// jo var pamatforma atšķirties no leksēmas pamatformas, piem. "otrās" pamatforma ir "otrā" nevis "otrais".
			// TODO - varbūt vienkārši dažām paradigmām vai galotnēm vajag karodziņu par to, ka jāģenerē pamatforma no jauna?
		}
	}

	public Wordform (String token) {
		this.token = token;
	}

	public Wordform(Node node) {
		super(node);
		if (!node.getNodeName().equalsIgnoreCase("Vārdforma")) throw new Error("Node " + node.getNodeName() + " nav Vārdforma");
		token = node.getAttributes().getNamedItem("vārds").getTextContent();
	}

	//getLocījumuDemo
/*	public String getDemo() {
		return this.getValue("LocījumuDemo");
		// TODO : apskatīt kur lieto un vai vajag
	} //*/

	public void shortDescription(PrintWriter stream) {
		stream.printf("%s :\t%s : %s  #%d\n", token, getTag(), getValue(AttributeNames.i_Lemma),lexeme.getID());
		//FIXME - nečeko, vai leksēma nav null
	}

	/**
	 * For debugging purposes only.
	 */
	public void longDescription(PrintStream out)
	{
		out.println(this.token + ":");
		for (String s : this.attributes.keySet())
		{
			out.println(s + "\t" + attributes.get(s));
		}
	}

	@Override
	public Object clone() {
		Wordform kopija;
		try {
			kopija = (Wordform)super.clone();
			kopija.token = this.token;
			kopija.lexeme = this.lexeme;
			kopija.ending = this.ending;
			return kopija;
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public void toXML (Writer stream) throws IOException {
		stream.write("<Vārdforma");
		stream.write(" vārds=\""+token.replace("\"", """)+"\">\n");
		super.toXML(stream); // īpašības UzXML
		stream.write("</Vārdforma>\n");
	}

	public Ending getEnding() {
		return ending;
	}

	public void setEnding(Ending ending) {
		this.ending = ending;
	}

	public String getToken() {
		return token;
	}

	protected void setToken(String newtoken) {
		token = newtoken;
		addAttribute(AttributeNames.i_Word, newtoken);
	}

    @Override
    public boolean equals(Object other) {
        if (other == null || !(other instanceof Wordform)) {
            return false;
        }
        Wordform that = (Wordform) other;
        if (this.attributes == null) {
            if (that.attributes != null) return false;
        } else if (!this.attributes.equals(that.attributes))
            return false;

        if (this.token == null) {
            if (that.token != null) return false;
        } else if (!this.token.equals(that.token))
            return false;

        if (this.ending == null) {
            if (that.ending != null) return false;
        } else if (!this.ending.equals(that.ending))
            return false;

        if (this.lexeme == null) {
            if (that.lexeme != null) return false;
        } else if (!this.lexeme.equals(that.lexeme))
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int hashCode = this.attributes.hashCode();
        if (token != null)
            hashCode = hashCode * 37 + token.hashCode();
        if (ending != null)
            hashCode = hashCode * 37 + ending.hashCode();
        if (lexeme != null)
            hashCode = hashCode * 37 + lexeme.hashCode();
        return hashCode;
    }
}


/*******************************************************************************
 * Copyright 2008, 2009, 2014 Institute of Mathematics and Computer Science, University of Latvia
 * Author: Pēteris Paikens
 *
 *     This program 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.
 *
 *     This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package lv.semti.morphology.analyzer;

import lv.semti.morphology.attributes.*;

/**
 * Transforms between internal attribute value structure and SemTi-Kamols
 * tagset.
 * @deprecated use lv.semti.morphology.attributes.TagSet instead
 * @author Pēteris Paikens
 */
@Deprecated
public class MarkupConverter {
	public static boolean defaulti = false;

	/**
	 * Check if attribute-value structure has attribute matching given
	 * attributeValue and if so then set corresponding position in the tag.
	 */
	private static void verifyAndSetKamolsAttribute(
			AttributeValues avs, StringBuilder tag, int index,
			char tagValue, String attribute, String attributeValue) {
		if (avs.isMatchingStrong(attribute, attributeValue))
			tag.setCharAt(index, tagValue);
	}

	/**
	 * Convert internal attribute-value structure to SemTi-Kamols tag.
	 */
	public static String toKamolsMarkup(AttributeValues avs) {
		StringBuilder res = toKamolsMarkup(avs, defaulti);
		if (res.length() < 1) return res.toString();

		// if (res.charAt(0) == 'v' && res.charAt(1) == '_') res.setCharAt(1, 'm'); PP 2012.12.07 - nezinu kāpēc tas te ir, bet tas čakarē tagošanu (jo tagsvm.... neatbilst nevienam varēt vai būt verbam)
		// if (res.charAt(0) == 'p' && res.charAt(6) == '_') res.setCharAt(6, 'n');
		// if (res.charAt(0) == 'v' && res.charAt(3) != 'p' && res.charAt(10) == '_')	res.setCharAt(10, 'n');
		return res.toString();
	}

	/**
	 * Convert internal attribute-value structure to SemTi-Kamols tag.
	 * No default values are set.
	 */
	public static String toKamolsMarkupNoDefaults(AttributeValues avs)
	{
		return toKamolsMarkup(avs, false).toString();
	}

	/**
	 * Convert internal attribute-value structure to SemTi-Kamols tag.
	 * Usage of default tags given as parameter. No additional defaults used.
	 */
	private static StringBuilder toKamolsMarkup(
			AttributeValues avs, boolean defaults) {

		StringBuilder tag = new StringBuilder();

		String pos = avs.getValue(AttributeNames.i_PartOfSpeech);
		if (pos == null) return tag;

		if (pos.equalsIgnoreCase(AttributeNames.v_Noun)) {

			tag.setLength(0);
			if (defaults)
				tag.append("ncmsnn");
			else tag.append("n_____");

			verifyAndSetKamolsAttribute(avs,tag,1,'c',AttributeNames.i_NounType,AttributeNames.v_CommonNoun);
			verifyAndSetKamolsAttribute(avs,tag,1,'p',AttributeNames.i_NounType,AttributeNames.v_ProperNoun);
			verifyAndSetKamolsAttribute(avs,tag,2,'m',AttributeNames.i_Gender,AttributeNames.v_Masculine);
			verifyAndSetKamolsAttribute(avs,tag,2,'f',AttributeNames.i_Gender,AttributeNames.v_Feminine);
			verifyAndSetKamolsAttribute(avs,tag,2,'k',AttributeNames.i_Gender,AttributeNames.v_Kopdzimte); //? nav TagSet
			//Tagset toties ir "Nepiemīt" dzimte
			verifyAndSetKamolsAttribute(avs,tag,3,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
			verifyAndSetKamolsAttribute(avs,tag,3,'v',AttributeNames.i_NumberSpecial,AttributeNames.v_SingulareTantum);
			verifyAndSetKamolsAttribute(avs,tag,3,'p',AttributeNames.i_Number,AttributeNames.v_Plural);
			verifyAndSetKamolsAttribute(avs,tag,3,'d',AttributeNames.i_NumberSpecial,AttributeNames.v_PlurareTantum);
			//Tagset toties ir "Nepiemīt" skaitlis
			verifyAndSetKamolsAttribute(avs,tag,4,'n',AttributeNames.i_Case,AttributeNames.v_Nominative);
			verifyAndSetKamolsAttribute(avs,tag,4,'g',AttributeNames.i_Case,AttributeNames.v_Genitive);
			verifyAndSetKamolsAttribute(avs,tag,4,'s',AttributeNames.i_Declension,AttributeNames.v_InflexibleGenitive);
			verifyAndSetKamolsAttribute(avs,tag,4,'d',AttributeNames.i_Case,AttributeNames.v_Dative);
			verifyAndSetKamolsAttribute(avs,tag,4,'a',AttributeNames.i_Case,AttributeNames.v_Accusative);
			verifyAndSetKamolsAttribute(avs,tag,4,'v',AttributeNames.i_Case,AttributeNames.v_Vocative);
			verifyAndSetKamolsAttribute(avs,tag,4,'l',AttributeNames.i_Case,AttributeNames.v_Locative);
			verifyAndSetKamolsAttribute(avs,tag,4,'u',AttributeNames.i_Case,AttributeNames.v_Nelokaams); // ? nav TagSet
			//Tagset toties ir "Nepiemīt" locījums

			verifyAndSetKamolsAttribute(avs,tag,5,'1',AttributeNames.i_Declension,"1");
			verifyAndSetKamolsAttribute(avs,tag,5,'2',AttributeNames.i_Declension,"2");
			verifyAndSetKamolsAttribute(avs,tag,5,'3',AttributeNames.i_Declension,"3");
			verifyAndSetKamolsAttribute(avs,tag,5,'4',AttributeNames.i_Declension,"4");
			verifyAndSetKamolsAttribute(avs,tag,5,'5',AttributeNames.i_Declension,"5");
			verifyAndSetKamolsAttribute(avs,tag,5,'6',AttributeNames.i_Declension,"6");
			verifyAndSetKamolsAttribute(avs,tag,5,'r',AttributeNames.i_Declension,AttributeNames.v_Reflexive);
			verifyAndSetKamolsAttribute(avs,tag,5,'0',AttributeNames.i_Declension,AttributeNames.v_NA);
		}
		else if (pos.equalsIgnoreCase(AttributeNames.v_Verb) && !avs.isMatchingStrong(AttributeNames.i_Izteiksme, AttributeNames.v_Participle)) {

			tag.setLength(0);
			if (defaults)
				tag.append("vmni0t1000n");
			//else tag.append("vm_________");
			else tag.append("v__________");

			verifyAndSetKamolsAttribute(avs,tag,1,'m',AttributeNames.i_VerbType,AttributeNames.v_MainVerb);
			verifyAndSetKamolsAttribute(avs,tag,1,'a',AttributeNames.i_VerbType,AttributeNames.v_PaliigDv);
			verifyAndSetKamolsAttribute(avs,tag,1,'o',AttributeNames.i_VerbType,AttributeNames.v_Modaals);
			verifyAndSetKamolsAttribute(avs,tag,1,'p',AttributeNames.i_VerbType,AttributeNames.v_Faazes);
			verifyAndSetKamolsAttribute(avs,tag,1,'e',AttributeNames.i_VerbType,AttributeNames.v_IzpausmesVeida);
			verifyAndSetKamolsAttribute(avs,tag,1,'c',AttributeNames.i_VerbType,AttributeNames.v_Buut);
			verifyAndSetKamolsAttribute(avs,tag,1,'t',AttributeNames.i_VerbType,AttributeNames.v_TiktTapt);
			verifyAndSetKamolsAttribute(avs,tag,1,'g',AttributeNames.i_VerbType,AttributeNames.v_Nebuut);

			verifyAndSetKamolsAttribute(avs,tag,2,'n',AttributeNames.i_Reflexive,AttributeNames.v_No);
			verifyAndSetKamolsAttribute(avs,tag,2,'y',AttributeNames.i_Reflexive,AttributeNames.v_Yes);

			verifyAndSetKamolsAttribute(avs,tag,3,'i',AttributeNames.i_Izteiksme,AttributeNames.v_Iisteniibas);
			verifyAndSetKamolsAttribute(avs,tag,3,'r',AttributeNames.i_Izteiksme,AttributeNames.v_Atstaastiijuma);
			verifyAndSetKamolsAttribute(avs,tag,3,'c',AttributeNames.i_Izteiksme,AttributeNames.v_Veeleejuma);
			verifyAndSetKamolsAttribute(avs,tag,3,'d',AttributeNames.i_Izteiksme,AttributeNames.v_Vajadziibas);
			verifyAndSetKamolsAttribute(avs,tag,3,'m',AttributeNames.i_Izteiksme,AttributeNames.v_Paveeles);
			verifyAndSetKamolsAttribute(avs,tag,3,'n',AttributeNames.i_Izteiksme,AttributeNames.v_Nenoteiksme);
			verifyAndSetKamolsAttribute(avs,tag,3,'p',AttributeNames.i_Izteiksme,AttributeNames.v_Participle);

			verifyAndSetKamolsAttribute(avs,tag,4,'p',AttributeNames.i_Laiks,AttributeNames.v_Tagadne);
			verifyAndSetKamolsAttribute(avs,tag,4,'f',AttributeNames.i_Laiks,AttributeNames.v_Naakotne);
			verifyAndSetKamolsAttribute(avs,tag,4,'s',AttributeNames.i_Laiks,AttributeNames.v_Pagaatne);
			verifyAndSetKamolsAttribute(avs,tag,4,'0',AttributeNames.i_Laiks,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,5,'t',AttributeNames.i_Transitivity,AttributeNames.v_Transitive);
			verifyAndSetKamolsAttribute(avs,tag,5,'i',AttributeNames.i_Transitivity,AttributeNames.v_Intransitive);
			verifyAndSetKamolsAttribute(avs,tag,5,'0',AttributeNames.i_Transitivity,AttributeNames.v_NA);  //? Nav tagset

			verifyAndSetKamolsAttribute(avs,tag,6,'1',AttributeNames.i_Konjugaacija,"1");
			verifyAndSetKamolsAttribute(avs,tag,6,'2',AttributeNames.i_Konjugaacija,"2");
			verifyAndSetKamolsAttribute(avs,tag,6,'3',AttributeNames.i_Konjugaacija,"3");
			verifyAndSetKamolsAttribute(avs,tag,6,'i',AttributeNames.i_Konjugaacija,AttributeNames.v_Nekaartns);
			verifyAndSetKamolsAttribute(avs,tag,6,'0',AttributeNames.i_Konjugaacija,AttributeNames.v_NA);  //? Nav tagset

			verifyAndSetKamolsAttribute(avs,tag,7,'1',AttributeNames.i_Person,"1");
			verifyAndSetKamolsAttribute(avs,tag,7,'2',AttributeNames.i_Person,"2");
			verifyAndSetKamolsAttribute(avs,tag,7,'3',AttributeNames.i_Person,"3");
			verifyAndSetKamolsAttribute(avs,tag,7,'0',AttributeNames.i_Person,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,8,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
			verifyAndSetKamolsAttribute(avs,tag,8,'p',AttributeNames.i_Number,AttributeNames.v_Plural);
			verifyAndSetKamolsAttribute(avs,tag,8,'0',AttributeNames.i_Number,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,9,'a',AttributeNames.i_Voice,AttributeNames.v_Active);
			verifyAndSetKamolsAttribute(avs,tag,9,'p',AttributeNames.i_Voice,AttributeNames.v_Passive);
			verifyAndSetKamolsAttribute(avs,tag,9,'0',AttributeNames.i_Voice,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,10,'y',AttributeNames.i_Noliegums,AttributeNames.v_Yes);
			verifyAndSetKamolsAttribute(avs,tag,10,'n',AttributeNames.i_Noliegums,AttributeNames.v_No);

			//verifyAndSetKamolsAttribute(avs,tag,10,'n',AttributeNames.i_Noliegums,null);
		}
		else if (pos.equalsIgnoreCase(AttributeNames.v_Verb) && avs.isMatchingStrong(AttributeNames.i_Izteiksme, AttributeNames.v_Participle)) {
			tag.setLength(0);
			if (defaults)
				tag.append("vmnpdmsnapn");
			else tag.append("v__p_______");

			verifyAndSetKamolsAttribute(avs,tag,1,'m',AttributeNames.i_VerbType,AttributeNames.v_MainVerb);
			verifyAndSetKamolsAttribute(avs,tag,1,'a',AttributeNames.i_VerbType,AttributeNames.v_PaliigDv);
			verifyAndSetKamolsAttribute(avs,tag,1,'o',AttributeNames.i_VerbType,AttributeNames.v_Modaals);
			verifyAndSetKamolsAttribute(avs,tag,1,'p',AttributeNames.i_VerbType,AttributeNames.v_Faazes);
			verifyAndSetKamolsAttribute(avs,tag,1,'e',AttributeNames.i_VerbType,AttributeNames.v_IzpausmesVeida);
			verifyAndSetKamolsAttribute(avs,tag,1,'c',AttributeNames.i_VerbType,AttributeNames.v_Buut);
			verifyAndSetKamolsAttribute(avs,tag,1,'t',AttributeNames.i_VerbType,AttributeNames.v_TiktTapt);
			verifyAndSetKamolsAttribute(avs,tag,1,'g',AttributeNames.i_VerbType,AttributeNames.v_Nebuut);

			verifyAndSetKamolsAttribute(avs,tag,2,'n',AttributeNames.i_Reflexive,AttributeNames.v_No);
			verifyAndSetKamolsAttribute(avs,tag,2,'y',AttributeNames.i_Reflexive,AttributeNames.v_Yes);

			verifyAndSetKamolsAttribute(avs,tag,3,'i',AttributeNames.i_Izteiksme,AttributeNames.v_Iisteniibas);
			verifyAndSetKamolsAttribute(avs,tag,3,'r',AttributeNames.i_Izteiksme,AttributeNames.v_Atstaastiijuma);
			verifyAndSetKamolsAttribute(avs,tag,3,'c',AttributeNames.i_Izteiksme,AttributeNames.v_Veeleejuma);
			verifyAndSetKamolsAttribute(avs,tag,3,'d',AttributeNames.i_Izteiksme,AttributeNames.v_Vajadziibas);
			verifyAndSetKamolsAttribute(avs,tag,3,'m',AttributeNames.i_Izteiksme,AttributeNames.v_Paveeles);
			verifyAndSetKamolsAttribute(avs,tag,3,'n',AttributeNames.i_Izteiksme,AttributeNames.v_Nenoteiksme);
			verifyAndSetKamolsAttribute(avs,tag,3,'p',AttributeNames.i_Izteiksme,AttributeNames.v_Participle);

			verifyAndSetKamolsAttribute(avs,tag,4,'d',AttributeNames.i_Lokaamiiba,AttributeNames.v_Lokaams);
			verifyAndSetKamolsAttribute(avs,tag,4,'p',AttributeNames.i_Lokaamiiba,AttributeNames.v_DaljeejiLokaams);
			verifyAndSetKamolsAttribute(avs,tag,4,'u',AttributeNames.i_Lokaamiiba,AttributeNames.v_Nelokaams);

			verifyAndSetKamolsAttribute(avs,tag,5,'m',AttributeNames.i_Gender,AttributeNames.v_Masculine);
			verifyAndSetKamolsAttribute(avs,tag,5,'f',AttributeNames.i_Gender,AttributeNames.v_Feminine);
			verifyAndSetKamolsAttribute(avs,tag,5,'0',AttributeNames.i_Gender,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,6,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
			verifyAndSetKamolsAttribute(avs,tag,6,'p',AttributeNames.i_Number,AttributeNames.v_Plural);
			verifyAndSetKamolsAttribute(avs,tag,6,'0',AttributeNames.i_Number,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,7,'n',AttributeNames.i_Case,AttributeNames.v_Nominative);
			verifyAndSetKamolsAttribute(avs,tag,7,'g',AttributeNames.i_Case,AttributeNames.v_Genitive);
			verifyAndSetKamolsAttribute(avs,tag,7,'d',AttributeNames.i_Case,AttributeNames.v_Dative);
			verifyAndSetKamolsAttribute(avs,tag,7,'a',AttributeNames.i_Case,AttributeNames.v_Accusative);
			verifyAndSetKamolsAttribute(avs,tag,7,'v',AttributeNames.i_Case,AttributeNames.v_Vocative);
			verifyAndSetKamolsAttribute(avs,tag,7,'l',AttributeNames.i_Case,AttributeNames.v_Locative);
			verifyAndSetKamolsAttribute(avs,tag,7,'0',AttributeNames.i_Case,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,8,'a',AttributeNames.i_Voice,AttributeNames.v_Active);
			verifyAndSetKamolsAttribute(avs,tag,8,'p',AttributeNames.i_Voice,AttributeNames.v_Passive);
			verifyAndSetKamolsAttribute(avs,tag,8,'0',AttributeNames.i_Voice,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,9,'p',AttributeNames.i_Laiks,AttributeNames.v_Tagadne);
			verifyAndSetKamolsAttribute(avs,tag,9,'s',AttributeNames.i_Laiks,AttributeNames.v_Pagaatne);
			verifyAndSetKamolsAttribute(avs,tag,9,'f',AttributeNames.i_Laiks,AttributeNames.v_Naakotne);
			verifyAndSetKamolsAttribute(avs,tag,9,'0',AttributeNames.i_Laiks,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,10,'n',AttributeNames.i_Definiteness,AttributeNames.v_Indefinite);
			verifyAndSetKamolsAttribute(avs,tag,10,'y',AttributeNames.i_Definiteness,AttributeNames.v_Definite);
			verifyAndSetKamolsAttribute(avs,tag,10,'0',AttributeNames.i_Definiteness,AttributeNames.v_NA);
		}
		else if (pos.equalsIgnoreCase(AttributeNames.v_Adjective)) {

			tag.setLength(0);
			if (defaults)
				tag.append("afmsnnp");
			else tag.append("a______");

			verifyAndSetKamolsAttribute(avs,tag,1,'f',AttributeNames.i_AdjectiveType,AttributeNames.v_QualificativeAdjective);
			verifyAndSetKamolsAttribute(avs,tag,1,'r',AttributeNames.i_AdjectiveType,AttributeNames.v_RelativeAdjective);

			verifyAndSetKamolsAttribute(avs,tag,2,'m',AttributeNames.i_Gender,AttributeNames.v_Masculine);
			verifyAndSetKamolsAttribute(avs,tag,2,'f',AttributeNames.i_Gender,AttributeNames.v_Feminine);

			verifyAndSetKamolsAttribute(avs,tag,3,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
			verifyAndSetKamolsAttribute(avs,tag,3,'p',AttributeNames.i_Number,AttributeNames.v_Plural);

			verifyAndSetKamolsAttribute(avs,tag,4,'n',AttributeNames.i_Case,AttributeNames.v_Nominative);
			verifyAndSetKamolsAttribute(avs,tag,4,'g',AttributeNames.i_Case,AttributeNames.v_Genitive);
			verifyAndSetKamolsAttribute(avs,tag,4,'d',AttributeNames.i_Case,AttributeNames.v_Dative);
			verifyAndSetKamolsAttribute(avs,tag,4,'a',AttributeNames.i_Case,AttributeNames.v_Accusative);
			verifyAndSetKamolsAttribute(avs,tag,4,'v',AttributeNames.i_Case,AttributeNames.v_Vocative);
			verifyAndSetKamolsAttribute(avs,tag,4,'l',AttributeNames.i_Case,AttributeNames.v_Locative);

			verifyAndSetKamolsAttribute(avs,tag,5,'n',AttributeNames.i_Definiteness,AttributeNames.v_Indefinite);
			verifyAndSetKamolsAttribute(avs,tag,5,'y',AttributeNames.i_Definiteness,AttributeNames.v_Definite);

			verifyAndSetKamolsAttribute(avs,tag,6,'p',AttributeNames.i_Degree,AttributeNames.v_Positive);
			verifyAndSetKamolsAttribute(avs,tag,6,'c',AttributeNames.i_Degree,AttributeNames.v_Comparative);
			verifyAndSetKamolsAttribute(avs,tag,6,'s',AttributeNames.i_Degree,AttributeNames.v_Superlative);
		}
		else if (pos.equalsIgnoreCase(AttributeNames.v_Pronoun)) {

			tag.setLength(0);
			if (defaults)
				tag.append("pp1msnn");
			else tag.append("p______");

			verifyAndSetKamolsAttribute(avs,tag,1,'p',AttributeNames.i_VvTips,AttributeNames.v_Personu);
			verifyAndSetKamolsAttribute(avs,tag,1,'x',AttributeNames.i_VvTips,AttributeNames.v_Atgriezeniskie);
			verifyAndSetKamolsAttribute(avs,tag,1,'s',AttributeNames.i_VvTips,AttributeNames.v_Piederiibas);
			verifyAndSetKamolsAttribute(avs,tag,1,'d',AttributeNames.i_VvTips,AttributeNames.v_Noraadaamie);
			verifyAndSetKamolsAttribute(avs,tag,1,'i',AttributeNames.i_VvTips,AttributeNames.v_Nenoteiktie);
			verifyAndSetKamolsAttribute(avs,tag,1,'q',AttributeNames.i_VvTips,AttributeNames.v_Jautaajamie);
			verifyAndSetKamolsAttribute(avs,tag,1,'r',AttributeNames.i_VvTips,AttributeNames.v_AttieksmesVv);
			verifyAndSetKamolsAttribute(avs,tag,1,'g',AttributeNames.i_VvTips,AttributeNames.v_Noteiktie);

			verifyAndSetKamolsAttribute(avs,tag,2,'1',AttributeNames.i_Person,"1");
			verifyAndSetKamolsAttribute(avs,tag,2,'2',AttributeNames.i_Person,"2");
			verifyAndSetKamolsAttribute(avs,tag,2,'3',AttributeNames.i_Person,"3");
			verifyAndSetKamolsAttribute(avs,tag,2,'0',AttributeNames.i_Person,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,3,'m',AttributeNames.i_Gender,AttributeNames.v_Masculine);
			verifyAndSetKamolsAttribute(avs,tag,3,'f',AttributeNames.i_Gender,AttributeNames.v_Feminine);
			verifyAndSetKamolsAttribute(avs,tag,3,'0',AttributeNames.i_Gender,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,4,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
			verifyAndSetKamolsAttribute(avs,tag,4,'p',AttributeNames.i_Number,AttributeNames.v_Plural);
			verifyAndSetKamolsAttribute(avs,tag,4,'0',AttributeNames.i_Number,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,5,'n',AttributeNames.i_Case,AttributeNames.v_Nominative);
			verifyAndSetKamolsAttribute(avs,tag,5,'g',AttributeNames.i_Case,AttributeNames.v_Genitive);
			verifyAndSetKamolsAttribute(avs,tag,5,'d',AttributeNames.i_Case,AttributeNames.v_Dative);
			verifyAndSetKamolsAttribute(avs,tag,5,'a',AttributeNames.i_Case,AttributeNames.v_Accusative);
			verifyAndSetKamolsAttribute(avs,tag,5,'v',AttributeNames.i_Case,AttributeNames.v_Vocative);
			verifyAndSetKamolsAttribute(avs,tag,5,'l',AttributeNames.i_Case,AttributeNames.v_Locative);
			verifyAndSetKamolsAttribute(avs,tag,5,'u',AttributeNames.i_Case,AttributeNames.v_Nelokaams);

			verifyAndSetKamolsAttribute(avs,tag,6,'n',AttributeNames.i_Noliegums,AttributeNames.v_No);
			verifyAndSetKamolsAttribute(avs,tag,6,'y',AttributeNames.i_Noliegums,AttributeNames.v_Yes);
		}
		else if (pos.equalsIgnoreCase(AttributeNames.v_Adverb)) {

			tag.setLength(0);
			if (defaults)
				tag.append("rp_");
			else tag.append("r__");

			verifyAndSetKamolsAttribute(avs,tag,1,'r',AttributeNames.i_Degree,AttributeNames.v_Relative);
			verifyAndSetKamolsAttribute(avs,tag,1,'p',AttributeNames.i_Degree,AttributeNames.v_Positive);
			verifyAndSetKamolsAttribute(avs,tag,1,'c',AttributeNames.i_Degree,AttributeNames.v_Comparative);
			verifyAndSetKamolsAttribute(avs,tag,1,'s',AttributeNames.i_Degree,AttributeNames.v_Superlative);
			verifyAndSetKamolsAttribute(avs,tag,1,'0',AttributeNames.i_Degree,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,2,'q',AttributeNames.i_ApstTips,AttributeNames.v_Meera);
			verifyAndSetKamolsAttribute(avs,tag,2,'m',AttributeNames.i_ApstTips,AttributeNames.v_Veida);
			verifyAndSetKamolsAttribute(avs,tag,2,'p',AttributeNames.i_ApstTips,AttributeNames.v_Vietas);
			verifyAndSetKamolsAttribute(avs,tag,2,'t',AttributeNames.i_ApstTips,AttributeNames.v_Laika);
			verifyAndSetKamolsAttribute(avs,tag,2,'c',AttributeNames.i_ApstTips,AttributeNames.v_Ceelonja);
		}
		else if (pos.equalsIgnoreCase(AttributeNames.v_Preposition)) {

			tag.setLength(0);
			if (defaults)
				tag.append("sppgn");
			else tag.append("s____");

			verifyAndSetKamolsAttribute(avs,tag,1,'p',AttributeNames.i_Novietojums,AttributeNames.v_Pirms);
			verifyAndSetKamolsAttribute(avs,tag,1,'t',AttributeNames.i_Novietojums,AttributeNames.v_Peec);

			verifyAndSetKamolsAttribute(avs,tag,2,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
			verifyAndSetKamolsAttribute(avs,tag,2,'p',AttributeNames.i_Number,AttributeNames.v_Plural);
			verifyAndSetKamolsAttribute(avs,tag,2,'0',AttributeNames.i_Number,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,3,'g',AttributeNames.i_Rekcija,AttributeNames.v_Genitive);
			verifyAndSetKamolsAttribute(avs,tag,3,'d',AttributeNames.i_Rekcija,AttributeNames.v_Dative);
			verifyAndSetKamolsAttribute(avs,tag,3,'a',AttributeNames.i_Rekcija,AttributeNames.v_Accusative);
			verifyAndSetKamolsAttribute(avs,tag,3,'0',AttributeNames.i_Rekcija,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,4,'y',AttributeNames.i_VietasApstNoziime,AttributeNames.v_Yes);
			verifyAndSetKamolsAttribute(avs,tag,4,'n',AttributeNames.i_VietasApstNoziime,AttributeNames.v_No);
		}
		else if (pos.equalsIgnoreCase(AttributeNames.v_Conjunction)) {

			tag.setLength(0);
			if (defaults)
				tag.append("ccs");
			else tag.append("c__");

			verifyAndSetKamolsAttribute(avs,tag,1,'c',AttributeNames.i_SaikljaTips,AttributeNames.v_Sakaartojuma);
			verifyAndSetKamolsAttribute(avs,tag,1,'s',AttributeNames.i_SaikljaTips,AttributeNames.v_Pakaartojuma);

			verifyAndSetKamolsAttribute(avs,tag,2,'s',AttributeNames.i_Uzbuuve,AttributeNames.v_Vienkaarshs);
			verifyAndSetKamolsAttribute(avs,tag,2,'d',AttributeNames.i_Uzbuuve,AttributeNames.v_Divkaarshs);
			verifyAndSetKamolsAttribute(avs,tag,2,'c',AttributeNames.i_Uzbuuve,AttributeNames.v_Salikts);
			verifyAndSetKamolsAttribute(avs,tag,2,'r',AttributeNames.i_Uzbuuve,AttributeNames.v_Atkaartots);
		}
		else if (pos.equalsIgnoreCase(AttributeNames.v_Numeral)) {

			tag.setLength(0);
			if (defaults)
				tag.append("mcs_snv");
			else tag.append("m______");

			verifyAndSetKamolsAttribute(avs,tag,1,'c',AttributeNames.i_SkaitljaTips,AttributeNames.v_PamataSv);
			verifyAndSetKamolsAttribute(avs,tag,1,'o',AttributeNames.i_SkaitljaTips,AttributeNames.v_Kaartas);
			verifyAndSetKamolsAttribute(avs,tag,1,'f',AttributeNames.i_SkaitljaTips,AttributeNames.v_Daljskaitlis);

			verifyAndSetKamolsAttribute(avs,tag,2,'s',AttributeNames.i_Uzbuuve,AttributeNames.v_Vienkaarshs);
			verifyAndSetKamolsAttribute(avs,tag,2,'c',AttributeNames.i_Uzbuuve,AttributeNames.v_Salikts);
			verifyAndSetKamolsAttribute(avs,tag,2,'j',AttributeNames.i_Uzbuuve,AttributeNames.v_Savienojums);

			verifyAndSetKamolsAttribute(avs,tag,3,'m',AttributeNames.i_Gender,AttributeNames.v_Masculine);
			verifyAndSetKamolsAttribute(avs,tag,3,'f',AttributeNames.i_Gender,AttributeNames.v_Feminine);
			verifyAndSetKamolsAttribute(avs,tag,3,'0',AttributeNames.i_Gender,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,4,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
			verifyAndSetKamolsAttribute(avs,tag,4,'p',AttributeNames.i_Number,AttributeNames.v_Plural);

			verifyAndSetKamolsAttribute(avs,tag,5,'n',AttributeNames.i_Case,AttributeNames.v_Nominative);
			verifyAndSetKamolsAttribute(avs,tag,5,'g',AttributeNames.i_Case,AttributeNames.v_Genitive);
			verifyAndSetKamolsAttribute(avs,tag,5,'d',AttributeNames.i_Case,AttributeNames.v_Dative);
			verifyAndSetKamolsAttribute(avs,tag,5,'a',AttributeNames.i_Case,AttributeNames.v_Accusative);
			verifyAndSetKamolsAttribute(avs,tag,5,'v',AttributeNames.i_Case,AttributeNames.v_Vocative);
			verifyAndSetKamolsAttribute(avs,tag,5,'l',AttributeNames.i_Case,AttributeNames.v_Locative);
			verifyAndSetKamolsAttribute(avs,tag,5,'0',AttributeNames.i_Case,AttributeNames.v_NA);

			verifyAndSetKamolsAttribute(avs,tag,6,'v',AttributeNames.i_Order,AttributeNames.v_Ones);
			verifyAndSetKamolsAttribute(avs,tag,6,'p',AttributeNames.i_Order,AttributeNames.v_Teens);
			verifyAndSetKamolsAttribute(avs,tag,6,'d',AttributeNames.i_Order,AttributeNames.v_Tens);
			verifyAndSetKamolsAttribute(avs,tag,6,'s',AttributeNames.i_Order,AttributeNames.v_Hundreds);
			verifyAndSetKamolsAttribute(avs,tag,6,'t',AttributeNames.i_Order,AttributeNames.v_Thousands);
			verifyAndSetKamolsAttribute(avs,tag,6,'m',AttributeNames.i_Order,AttributeNames.v_Millions);
			verifyAndSetKamolsAttribute(avs,tag,6,'r',AttributeNames.i_Order,AttributeNames.v_Billions);
		}
		else if (pos.equalsIgnoreCase(AttributeNames.v_Interjection)) {

			tag.setLength(0);
			if (defaults)
				tag.append("is");
			else tag.append("i_");

			verifyAndSetKamolsAttribute(avs,tag,1,'s',AttributeNames.i_Uzbuuve,AttributeNames.v_Vienkaarshs);
			verifyAndSetKamolsAttribute(avs,tag,1,'c',AttributeNames.i_Uzbuuve,AttributeNames.v_Salikts);
		}
		else if (pos.equalsIgnoreCase(AttributeNames.v_Particle)) {

			tag.setLength(0);
			if (defaults)
				tag.append("qs");
			else tag.append("q_");

			verifyAndSetKamolsAttribute(avs,tag,1,'s',AttributeNames.i_Uzbuuve,AttributeNames.v_Vienkaarshs);
			verifyAndSetKamolsAttribute(avs,tag,1,'c',AttributeNames.i_Uzbuuve,AttributeNames.v_Salikts);
		}
		else if (pos.equalsIgnoreCase(AttributeNames.v_Punctuation)) {
			tag.setLength(0);
			if (defaults)
				tag.append("zc");
			else tag.append("z_");

			verifyAndSetKamolsAttribute(avs,tag,1,'c',AttributeNames.i_PieturziimesTips,AttributeNames.v_Komats);
			verifyAndSetKamolsAttribute(avs,tag,1,'q',AttributeNames.i_PieturziimesTips,AttributeNames.v_Peedinja);
			verifyAndSetKamolsAttribute(avs,tag,1,'s',AttributeNames.i_PieturziimesTips,AttributeNames.v_Punkts);
			verifyAndSetKamolsAttribute(avs,tag,1,'b',AttributeNames.i_PieturziimesTips,AttributeNames.v_Iekava);
			verifyAndSetKamolsAttribute(avs,tag,1,'d',AttributeNames.i_PieturziimesTips,AttributeNames.v_Domuziime);
			verifyAndSetKamolsAttribute(avs,tag,1,'o',AttributeNames.i_PieturziimesTips,AttributeNames.v_Kols);
			verifyAndSetKamolsAttribute(avs,tag,1,'x',AttributeNames.i_PieturziimesTips,AttributeNames.v_Cita);
		} else if (pos.equalsIgnoreCase(AttributeNames.v_Abbreviation)) {
			tag.setLength(0);
			tag.append("y");
		} else if (pos.equalsIgnoreCase(AttributeNames.v_Residual)) {
			tag.setLength(0);
			tag.append("xx");

			verifyAndSetKamolsAttribute(avs,tag,1,'f',AttributeNames.i_ResidualType,AttributeNames.v_Foreign);
			verifyAndSetKamolsAttribute(avs,tag,1,'t',AttributeNames.i_ResidualType,AttributeNames.v_Typo);
			verifyAndSetKamolsAttribute(avs,tag,1,'n',AttributeNames.i_ResidualType,AttributeNames.v_Number);
			verifyAndSetKamolsAttribute(avs,tag,1,'o',AttributeNames.i_ResidualType,AttributeNames.v_Ordinal);
			verifyAndSetKamolsAttribute(avs,tag,1,'u',AttributeNames.i_ResidualType,AttributeNames.v_URI);
		}

		return tag;
	}

	/**
	 * Check if tag has given value in specified position and if so then set
	 * corresponding attribute-value pair in the given attribute-value
	 * structure.
	 */
	private static void verifyAndSetAVSAttribute(
			String tag, FeatureStructure avs, int index, char tagValue,
			String attribute, String attributeValue) {
		//TODO - šī metode 'silently fails' uz jauniem variantiem/simboliem
		//marķējumā. Normāli atrisinās tikai šīs klases pāreja uz xml
		//konfigfaila apstrādi
		if (index >= tag.length()) return;
		if (tag.charAt(index) == tagValue)
			avs.addAttribute(attribute, attributeValue);
	}

	/**
	 * Remove formating from Kamols-style tag.
	 */
	public static String removeKamolsMarkupFormating(String tag){
		String result = "";
		if (!tag.contains(",")) return "x";

		int depth = 0;
		int commas = 0;
		for (char c : tag.toCharArray()) {
			if (c=='[') depth++;
			if (c==']') depth--;
			if (depth == 1 && c==',') commas++;

			if (commas == 2) result = result + c;
		}

		result = result.replaceAll("_[A-Z0-9]*"   ,   "_");
		result = result.replaceAll("(\\[|\\]|\\,| )","");
		return result;
	}

	/**
	 * Convert SemTi-Kamols markup tag to internal attribute-value structure.
	 */
	public static AttributeValues fromKamolsMarkup(String tag) {
		AttributeValues attributes = new AttributeValues();
		if (tag == null || tag.equals("")) return attributes;

		switch (tag.charAt(0)) {
		case 'n':
			attributes.addAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Noun);

			verifyAndSetAVSAttribute(tag,attributes,1,'c',AttributeNames.i_NounType,AttributeNames.v_CommonNoun);
			verifyAndSetAVSAttribute(tag,attributes,1,'p',AttributeNames.i_NounType,AttributeNames.v_ProperNoun);
			verifyAndSetAVSAttribute(tag,attributes,2,'m',AttributeNames.i_Gender,AttributeNames.v_Masculine);
			verifyAndSetAVSAttribute(tag,attributes,2,'f',AttributeNames.i_Gender,AttributeNames.v_Feminine);
			verifyAndSetAVSAttribute(tag,attributes,2,'k',AttributeNames.i_Gender,AttributeNames.v_Kopdzimte);
			verifyAndSetAVSAttribute(tag,attributes,3,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
			verifyAndSetAVSAttribute(tag,attributes,3,'v',AttributeNames.i_Number,AttributeNames.v_Singular);
			verifyAndSetAVSAttribute(tag,attributes,3,'v',AttributeNames.i_NumberSpecial,AttributeNames.v_SingulareTantum);
			verifyAndSetAVSAttribute(tag,attributes,3,'p',AttributeNames.i_Number,AttributeNames.v_Plural);
			verifyAndSetAVSAttribute(tag,attributes,3,'d',AttributeNames.i_Number,AttributeNames.v_Plural);
			verifyAndSetAVSAttribute(tag,attributes,3,'d',AttributeNames.i_NumberSpecial,AttributeNames.v_PlurareTantum);
			verifyAndSetAVSAttribute(tag,attributes,4,'n',AttributeNames.i_Case,AttributeNames.v_Nominative);
			verifyAndSetAVSAttribute(tag,attributes,4,'g',AttributeNames.i_Case,AttributeNames.v_Genitive);
			verifyAndSetAVSAttribute(tag,attributes,4,'s',AttributeNames.i_Case,AttributeNames.v_Genitive);
			verifyAndSetAVSAttribute(tag,attributes,4,'d',AttributeNames.i_Case,AttributeNames.v_Dative);
			verifyAndSetAVSAttribute(tag,attributes,4,'a',AttributeNames.i_Case,AttributeNames.v_Accusative);
			verifyAndSetAVSAttribute(tag,attributes,4,'v',AttributeNames.i_Case,AttributeNames.v_Vocative);
			verifyAndSetAVSAttribute(tag,attributes,4,'l',AttributeNames.i_Case,AttributeNames.v_Locative);
			verifyAndSetAVSAttribute(tag,attributes,5,'1',AttributeNames.i_Declension,"1");
			verifyAndSetAVSAttribute(tag,attributes,5,'2',AttributeNames.i_Declension,"2");
			verifyAndSetAVSAttribute(tag,attributes,5,'3',AttributeNames.i_Declension,"3");
			verifyAndSetAVSAttribute(tag,attributes,5,'4',AttributeNames.i_Declension,"4");
			verifyAndSetAVSAttribute(tag,attributes,5,'5',AttributeNames.i_Declension,"5");
			verifyAndSetAVSAttribute(tag,attributes,5,'6',AttributeNames.i_Declension,"6");
			verifyAndSetAVSAttribute(tag,attributes,5,'r',AttributeNames.i_Declension,AttributeNames.v_Reflexive);
			verifyAndSetAVSAttribute(tag,attributes,5,'0',AttributeNames.i_Declension,AttributeNames.v_NA);
			verifyAndSetAVSAttribute(tag,attributes,4,'s',AttributeNames.i_Declension,AttributeNames.v_InflexibleGenitive);
			break;
		case 'v':
			attributes.addAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Verb);

			if (tag.length()<4 || tag.charAt(3) != 'p') { // nav divdabis
				verifyAndSetAVSAttribute(tag,attributes,1,'m',AttributeNames.i_VerbType,AttributeNames.v_MainVerb);
				verifyAndSetAVSAttribute(tag,attributes,1,'a',AttributeNames.i_VerbType,AttributeNames.v_PaliigDv);
				verifyAndSetAVSAttribute(tag,attributes,1,'o',AttributeNames.i_VerbType,AttributeNames.v_Modaals);
				verifyAndSetAVSAttribute(tag,attributes,1,'p',AttributeNames.i_VerbType,AttributeNames.v_Faazes);
				verifyAndSetAVSAttribute(tag,attributes,1,'e',AttributeNames.i_VerbType,AttributeNames.v_IzpausmesVeida);
				verifyAndSetAVSAttribute(tag,attributes,1,'c',AttributeNames.i_VerbType,AttributeNames.v_Buut);
				verifyAndSetAVSAttribute(tag,attributes,1,'t',AttributeNames.i_VerbType,AttributeNames.v_TiktTapt);
				verifyAndSetAVSAttribute(tag,attributes,1,'g',AttributeNames.i_VerbType,AttributeNames.v_Nebuut);

				verifyAndSetAVSAttribute(tag,attributes,2,'n',AttributeNames.i_Reflexive,AttributeNames.v_No);
				verifyAndSetAVSAttribute(tag,attributes,2,'y',AttributeNames.i_Reflexive,AttributeNames.v_Yes);
				verifyAndSetAVSAttribute(tag,attributes,3,'i',AttributeNames.i_Izteiksme,AttributeNames.v_Iisteniibas);
				verifyAndSetAVSAttribute(tag,attributes,3,'r',AttributeNames.i_Izteiksme,AttributeNames.v_Atstaastiijuma);
				verifyAndSetAVSAttribute(tag,attributes,3,'c',AttributeNames.i_Izteiksme,AttributeNames.v_Veeleejuma);
				verifyAndSetAVSAttribute(tag,attributes,3,'d',AttributeNames.i_Izteiksme,AttributeNames.v_Vajadziibas);
				verifyAndSetAVSAttribute(tag,attributes,3,'m',AttributeNames.i_Izteiksme,AttributeNames.v_Paveeles);
				verifyAndSetAVSAttribute(tag,attributes,3,'n',AttributeNames.i_Izteiksme,AttributeNames.v_Nenoteiksme);
				verifyAndSetAVSAttribute(tag,attributes,3,'p',AttributeNames.i_Izteiksme,AttributeNames.v_Participle);
				verifyAndSetAVSAttribute(tag,attributes,4,'p',AttributeNames.i_Laiks,AttributeNames.v_Tagadne);
				verifyAndSetAVSAttribute(tag,attributes,4,'f',AttributeNames.i_Laiks,AttributeNames.v_Naakotne);
				verifyAndSetAVSAttribute(tag,attributes,4,'s',AttributeNames.i_Laiks,AttributeNames.v_Pagaatne);
				verifyAndSetAVSAttribute(tag,attributes,4,'0',AttributeNames.i_Laiks,AttributeNames.v_NA);
				verifyAndSetAVSAttribute(tag,attributes,5,'t',AttributeNames.i_Transitivity,AttributeNames.v_Transitive);
				verifyAndSetAVSAttribute(tag,attributes,5,'i',AttributeNames.i_Transitivity,AttributeNames.v_Intransitive);
				verifyAndSetAVSAttribute(tag,attributes,5,'0',AttributeNames.i_Transitivity,AttributeNames.v_NA);
				verifyAndSetAVSAttribute(tag,attributes,6,'1',AttributeNames.i_Konjugaacija,"1");
				verifyAndSetAVSAttribute(tag,attributes,6,'2',AttributeNames.i_Konjugaacija,"2");
				verifyAndSetAVSAttribute(tag,attributes,6,'3',AttributeNames.i_Konjugaacija,"3");
				verifyAndSetAVSAttribute(tag,attributes,6,'i',AttributeNames.i_Konjugaacija,AttributeNames.v_Nekaartns);
				verifyAndSetAVSAttribute(tag,attributes,6,'0',AttributeNames.i_Konjugaacija,AttributeNames.v_NA);
				verifyAndSetAVSAttribute(tag,attributes,7,'1',AttributeNames.i_Person,"1");
				verifyAndSetAVSAttribute(tag,attributes,7,'2',AttributeNames.i_Person,"2");
				verifyAndSetAVSAttribute(tag,attributes,7,'3',AttributeNames.i_Person,"3");
				verifyAndSetAVSAttribute(tag,attributes,7,'0',AttributeNames.i_Person,AttributeNames.v_NA);
				verifyAndSetAVSAttribute(tag,attributes,8,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
				verifyAndSetAVSAttribute(tag,attributes,8,'p',AttributeNames.i_Number,AttributeNames.v_Plural);
				verifyAndSetAVSAttribute(tag,attributes,8,'0',AttributeNames.i_Number,AttributeNames.v_NA);
				verifyAndSetAVSAttribute(tag,attributes,9,'a',AttributeNames.i_Voice,AttributeNames.v_Active);
				verifyAndSetAVSAttribute(tag,attributes,9,'p',AttributeNames.i_Voice,AttributeNames.v_Passive);
				verifyAndSetAVSAttribute(tag,attributes,9,'0',AttributeNames.i_Voice,AttributeNames.v_NA);
				verifyAndSetAVSAttribute(tag,attributes,10,'n',AttributeNames.i_Noliegums,AttributeNames.v_No);
				verifyAndSetAVSAttribute(tag,attributes,10,'y',AttributeNames.i_Noliegums,AttributeNames.v_Yes);

			} else { // ir divdabis
				verifyAndSetAVSAttribute(tag,attributes,1,'m',AttributeNames.i_VerbType,AttributeNames.v_MainVerb);
				verifyAndSetAVSAttribute(tag,attributes,1,'a',AttributeNames.i_VerbType,AttributeNames.v_PaliigDv);
				verifyAndSetAVSAttribute(tag,attributes,1,'o',AttributeNames.i_VerbType,AttributeNames.v_Modaals);
				verifyAndSetAVSAttribute(tag,attributes,1,'p',AttributeNames.i_VerbType,AttributeNames.v_Faazes);
				verifyAndSetAVSAttribute(tag,attributes,1,'e',AttributeNames.i_VerbType,AttributeNames.v_IzpausmesVeida);
				verifyAndSetAVSAttribute(tag,attributes,1,'c',AttributeNames.i_VerbType,AttributeNames.v_Buut);
				verifyAndSetAVSAttribute(tag,attributes,1,'t',AttributeNames.i_VerbType,AttributeNames.v_TiktTapt);
				verifyAndSetAVSAttribute(tag,attributes,1,'g',AttributeNames.i_VerbType,AttributeNames.v_Nebuut);

				verifyAndSetAVSAttribute(tag,attributes,2,'n',AttributeNames.i_Reflexive,AttributeNames.v_No);
				verifyAndSetAVSAttribute(tag,attributes,2,'y',AttributeNames.i_Reflexive,AttributeNames.v_Yes);
				verifyAndSetAVSAttribute(tag,attributes,3,'i',AttributeNames.i_Izteiksme,AttributeNames.v_Iisteniibas);
				verifyAndSetAVSAttribute(tag,attributes,3,'r',AttributeNames.i_Izteiksme,AttributeNames.v_Atstaastiijuma);
				verifyAndSetAVSAttribute(tag,attributes,3,'c',AttributeNames.i_Izteiksme,AttributeNames.v_Veeleejuma);
				verifyAndSetAVSAttribute(tag,attributes,3,'d',AttributeNames.i_Izteiksme,AttributeNames.v_Vajadziibas);
				verifyAndSetAVSAttribute(tag,attributes,3,'m',AttributeNames.i_Izteiksme,AttributeNames.v_Paveeles);
				verifyAndSetAVSAttribute(tag,attributes,3,'n',AttributeNames.i_Izteiksme,AttributeNames.v_Nenoteiksme);
				verifyAndSetAVSAttribute(tag,attributes,3,'p',AttributeNames.i_Izteiksme,AttributeNames.v_Participle);
				verifyAndSetAVSAttribute(tag,attributes,4,'d',AttributeNames.i_Lokaamiiba,AttributeNames.v_Lokaams);
				verifyAndSetAVSAttribute(tag,attributes,4,'p',AttributeNames.i_Lokaamiiba,AttributeNames.v_DaljeejiLokaams);
				verifyAndSetAVSAttribute(tag,attributes,4,'u',AttributeNames.i_Lokaamiiba,AttributeNames.v_Nelokaams);
				verifyAndSetAVSAttribute(tag,attributes,5,'m',AttributeNames.i_Gender,AttributeNames.v_Masculine);
				verifyAndSetAVSAttribute(tag,attributes,5,'f',AttributeNames.i_Gender,AttributeNames.v_Feminine);
				verifyAndSetAVSAttribute(tag,attributes,5,'0',AttributeNames.i_Gender,AttributeNames.v_NA);
				verifyAndSetAVSAttribute(tag,attributes,6,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
				verifyAndSetAVSAttribute(tag,attributes,6,'p',AttributeNames.i_Number,AttributeNames.v_Plural);
				verifyAndSetAVSAttribute(tag,attributes,6,'0',AttributeNames.i_Number,AttributeNames.v_NA);
				verifyAndSetAVSAttribute(tag,attributes,7,'n',AttributeNames.i_Case,AttributeNames.v_Nominative);
				verifyAndSetAVSAttribute(tag,attributes,7,'g',AttributeNames.i_Case,AttributeNames.v_Genitive);
				verifyAndSetAVSAttribute(tag,attributes,7,'d',AttributeNames.i_Case,AttributeNames.v_Dative);
				verifyAndSetAVSAttribute(tag,attributes,7,'a',AttributeNames.i_Case,AttributeNames.v_Accusative);
				verifyAndSetAVSAttribute(tag,attributes,7,'v',AttributeNames.i_Case,AttributeNames.v_Vocative);
				verifyAndSetAVSAttribute(tag,attributes,7,'l',AttributeNames.i_Case,AttributeNames.v_Locative);
				verifyAndSetAVSAttribute(tag,attributes,7,'0',AttributeNames.i_Case,AttributeNames.v_NA);
				verifyAndSetAVSAttribute(tag,attributes,8,'a',AttributeNames.i_Voice,AttributeNames.v_Active);
				verifyAndSetAVSAttribute(tag,attributes,8,'p',AttributeNames.i_Voice,AttributeNames.v_Passive);
				verifyAndSetAVSAttribute(tag,attributes,8,'0',AttributeNames.i_Voice,AttributeNames.v_NA);
				verifyAndSetAVSAttribute(tag,attributes,9,'p',AttributeNames.i_Laiks,AttributeNames.v_Tagadne);
				verifyAndSetAVSAttribute(tag,attributes,9,'f',AttributeNames.i_Laiks,AttributeNames.v_Naakotne);
				verifyAndSetAVSAttribute(tag,attributes,9,'s',AttributeNames.i_Laiks,AttributeNames.v_Pagaatne);
				verifyAndSetAVSAttribute(tag,attributes,9,'0',AttributeNames.i_Laiks,AttributeNames.v_NA);
				verifyAndSetAVSAttribute(tag,attributes,10,'n',AttributeNames.i_Definiteness,AttributeNames.v_Indefinite);
				verifyAndSetAVSAttribute(tag,attributes,10,'y',AttributeNames.i_Definiteness,AttributeNames.v_Definite);
				verifyAndSetAVSAttribute(tag,attributes,10,'0',AttributeNames.i_Definiteness,AttributeNames.v_NA);
			}
			break;
		case 'a':
			attributes.addAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Adjective);

			verifyAndSetAVSAttribute(tag,attributes,1,'f',AttributeNames.i_AdjectiveType,AttributeNames.v_QualificativeAdjective);
			verifyAndSetAVSAttribute(tag,attributes,1,'r',AttributeNames.i_AdjectiveType,AttributeNames.v_RelativeAdjective);
			verifyAndSetAVSAttribute(tag,attributes,2,'m',AttributeNames.i_Gender,AttributeNames.v_Masculine);
			verifyAndSetAVSAttribute(tag,attributes,2,'f',AttributeNames.i_Gender,AttributeNames.v_Feminine);
			verifyAndSetAVSAttribute(tag,attributes,3,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
			verifyAndSetAVSAttribute(tag,attributes,3,'p',AttributeNames.i_Number,AttributeNames.v_Plural);
			verifyAndSetAVSAttribute(tag,attributes,4,'n',AttributeNames.i_Case,AttributeNames.v_Nominative);
			verifyAndSetAVSAttribute(tag,attributes,4,'g',AttributeNames.i_Case,AttributeNames.v_Genitive);
			verifyAndSetAVSAttribute(tag,attributes,4,'d',AttributeNames.i_Case,AttributeNames.v_Dative);
			verifyAndSetAVSAttribute(tag,attributes,4,'a',AttributeNames.i_Case,AttributeNames.v_Accusative);
			verifyAndSetAVSAttribute(tag,attributes,4,'v',AttributeNames.i_Case,AttributeNames.v_Vocative);
			verifyAndSetAVSAttribute(tag,attributes,4,'l',AttributeNames.i_Case,AttributeNames.v_Locative);
			verifyAndSetAVSAttribute(tag,attributes,5,'n',AttributeNames.i_Definiteness,AttributeNames.v_Indefinite);
			verifyAndSetAVSAttribute(tag,attributes,5,'y',AttributeNames.i_Definiteness,AttributeNames.v_Definite);
			verifyAndSetAVSAttribute(tag,attributes,6,'p',AttributeNames.i_Degree,AttributeNames.v_Positive);
			verifyAndSetAVSAttribute(tag,attributes,6,'c',AttributeNames.i_Degree,AttributeNames.v_Comparative);
			verifyAndSetAVSAttribute(tag,attributes,6,'s',AttributeNames.i_Degree,AttributeNames.v_Superlative);
			break;
		case 'p':
			attributes.addAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Pronoun);

			verifyAndSetAVSAttribute(tag,attributes,1,'p',AttributeNames.i_VvTips,AttributeNames.v_Personu);
			verifyAndSetAVSAttribute(tag,attributes,1,'x',AttributeNames.i_VvTips,AttributeNames.v_Atgriezeniskie);
			verifyAndSetAVSAttribute(tag,attributes,1,'s',AttributeNames.i_VvTips,AttributeNames.v_Piederiibas);
			verifyAndSetAVSAttribute(tag,attributes,1,'d',AttributeNames.i_VvTips,AttributeNames.v_Noraadaamie);
			verifyAndSetAVSAttribute(tag,attributes,1,'i',AttributeNames.i_VvTips,AttributeNames.v_Nenoteiktie);
			verifyAndSetAVSAttribute(tag,attributes,1,'q',AttributeNames.i_VvTips,AttributeNames.v_Jautaajamie);
			verifyAndSetAVSAttribute(tag,attributes,1,'r',AttributeNames.i_VvTips,AttributeNames.v_AttieksmesVv);
			verifyAndSetAVSAttribute(tag,attributes,1,'g',AttributeNames.i_VvTips,AttributeNames.v_Noteiktie);

			verifyAndSetAVSAttribute(tag,attributes,2,'1',AttributeNames.i_Person,"1");
			verifyAndSetAVSAttribute(tag,attributes,2,'2',AttributeNames.i_Person,"2");
			verifyAndSetAVSAttribute(tag,attributes,2,'3',AttributeNames.i_Person,"3");
			verifyAndSetAVSAttribute(tag,attributes,2,'0',AttributeNames.i_Person,AttributeNames.v_NA);
			verifyAndSetAVSAttribute(tag,attributes,3,'m',AttributeNames.i_Gender,AttributeNames.v_Masculine);
			verifyAndSetAVSAttribute(tag,attributes,3,'f',AttributeNames.i_Gender,AttributeNames.v_Feminine);
			verifyAndSetAVSAttribute(tag,attributes,3,'0',AttributeNames.i_Gender,AttributeNames.v_NA);
			verifyAndSetAVSAttribute(tag,attributes,4,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
			verifyAndSetAVSAttribute(tag,attributes,4,'p',AttributeNames.i_Number,AttributeNames.v_Plural);
			verifyAndSetAVSAttribute(tag,attributes,4,'0',AttributeNames.i_Number,AttributeNames.v_NA);
			verifyAndSetAVSAttribute(tag,attributes,5,'n',AttributeNames.i_Case,AttributeNames.v_Nominative);
			verifyAndSetAVSAttribute(tag,attributes,5,'g',AttributeNames.i_Case,AttributeNames.v_Genitive);
			verifyAndSetAVSAttribute(tag,attributes,5,'d',AttributeNames.i_Case,AttributeNames.v_Dative);
			verifyAndSetAVSAttribute(tag,attributes,5,'a',AttributeNames.i_Case,AttributeNames.v_Accusative);
			verifyAndSetAVSAttribute(tag,attributes,5,'v',AttributeNames.i_Case,AttributeNames.v_Vocative);
			verifyAndSetAVSAttribute(tag,attributes,5,'l',AttributeNames.i_Case,AttributeNames.v_Locative);
			verifyAndSetAVSAttribute(tag,attributes,5,'u',AttributeNames.i_Case,AttributeNames.v_Nelokaams);
			verifyAndSetAVSAttribute(tag,attributes,6,'n',AttributeNames.i_Noliegums,AttributeNames.v_No);
			verifyAndSetAVSAttribute(tag,attributes,6,'y',AttributeNames.i_Noliegums,AttributeNames.v_Yes);
			verifyAndSetAVSAttribute(tag,attributes,7,'a',AttributeNames.i_Anafora,AttributeNames.v_Adjektiivu);
			verifyAndSetAVSAttribute(tag,attributes,7,'s',AttributeNames.i_Anafora,AttributeNames.v_Substantiivu);
			verifyAndSetAVSAttribute(tag,attributes,7,'0',AttributeNames.i_Anafora,AttributeNames.v_NA);
			break;

		case 'r':
			attributes.addAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Adverb);

			verifyAndSetAVSAttribute(tag,attributes,1,'p',AttributeNames.i_Degree,AttributeNames.v_Positive);
			verifyAndSetAVSAttribute(tag,attributes,1,'c',AttributeNames.i_Degree,AttributeNames.v_Comparative);
			verifyAndSetAVSAttribute(tag,attributes,1,'s',AttributeNames.i_Degree,AttributeNames.v_Superlative);
			verifyAndSetAVSAttribute(tag,attributes,1,'r',AttributeNames.i_Degree,AttributeNames.v_Relative);
			verifyAndSetAVSAttribute(tag,attributes,1,'0',AttributeNames.i_Degree,AttributeNames.v_NA);
			verifyAndSetAVSAttribute(tag,attributes,2,'q',AttributeNames.i_ApstTips,AttributeNames.v_Meera);
			verifyAndSetAVSAttribute(tag,attributes,2,'m',AttributeNames.i_ApstTips,AttributeNames.v_Veida);
			verifyAndSetAVSAttribute(tag,attributes,2,'p',AttributeNames.i_ApstTips,AttributeNames.v_Vietas);
			verifyAndSetAVSAttribute(tag,attributes,2,'t',AttributeNames.i_ApstTips,AttributeNames.v_Laika);
			verifyAndSetAVSAttribute(tag,attributes,2,'c',AttributeNames.i_ApstTips,AttributeNames.v_Ceelonja);
			break;

		case 's':
			attributes.addAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Preposition);

			verifyAndSetAVSAttribute(tag,attributes,1,'p',AttributeNames.i_Novietojums,AttributeNames.v_Pirms);
			verifyAndSetAVSAttribute(tag,attributes,1,'t',AttributeNames.i_Novietojums,AttributeNames.v_Peec);
			verifyAndSetAVSAttribute(tag,attributes,2,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
			verifyAndSetAVSAttribute(tag,attributes,2,'p',AttributeNames.i_Number,AttributeNames.v_Plural);
			verifyAndSetAVSAttribute(tag,attributes,2,'0',AttributeNames.i_Number,AttributeNames.v_NA);
			verifyAndSetAVSAttribute(tag,attributes,3,'g',AttributeNames.i_Rekcija,AttributeNames.v_Genitive);
			verifyAndSetAVSAttribute(tag,attributes,3,'d',AttributeNames.i_Rekcija,AttributeNames.v_Dative);
			verifyAndSetAVSAttribute(tag,attributes,3,'a',AttributeNames.i_Rekcija,AttributeNames.v_Accusative);
			verifyAndSetAVSAttribute(tag,attributes,3,'0',AttributeNames.i_Rekcija,AttributeNames.v_NA);
			verifyAndSetAVSAttribute(tag,attributes,4,'y',AttributeNames.i_VietasApstNoziime,AttributeNames.v_Yes);
			verifyAndSetAVSAttribute(tag,attributes,4,'n',AttributeNames.i_VietasApstNoziime,AttributeNames.v_No);

			break;

		case 'c':
			attributes.addAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Conjunction);

			verifyAndSetAVSAttribute(tag,attributes,1,'c',AttributeNames.i_SaikljaTips,AttributeNames.v_Sakaartojuma);
			verifyAndSetAVSAttribute(tag,attributes,1,'s',AttributeNames.i_SaikljaTips,AttributeNames.v_Pakaartojuma);
			verifyAndSetAVSAttribute(tag,attributes,2,'s',AttributeNames.i_Uzbuuve,AttributeNames.v_Vienkaarshs);
			verifyAndSetAVSAttribute(tag,attributes,2,'d',AttributeNames.i_Uzbuuve,AttributeNames.v_Divkaarshs);
			verifyAndSetAVSAttribute(tag,attributes,2,'c',AttributeNames.i_Uzbuuve,AttributeNames.v_Salikts);
			verifyAndSetAVSAttribute(tag,attributes,2,'r',AttributeNames.i_Uzbuuve,AttributeNames.v_Atkaartots);
			break;

		case 'm':
			attributes.addAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Numeral);

			verifyAndSetAVSAttribute(tag,attributes,1,'c',AttributeNames.i_SkaitljaTips,AttributeNames.v_PamataSv);
			verifyAndSetAVSAttribute(tag,attributes,1,'o',AttributeNames.i_SkaitljaTips,AttributeNames.v_Kaartas);
			verifyAndSetAVSAttribute(tag,attributes,1,'f',AttributeNames.i_SkaitljaTips,AttributeNames.v_Daljskaitlis);
			verifyAndSetAVSAttribute(tag,attributes,2,'s',AttributeNames.i_Uzbuuve,AttributeNames.v_Vienkaarshs);
			verifyAndSetAVSAttribute(tag,attributes,2,'c',AttributeNames.i_Uzbuuve,AttributeNames.v_Salikts);
			verifyAndSetAVSAttribute(tag,attributes,2,'j',AttributeNames.i_Uzbuuve,AttributeNames.v_Savienojums);
			verifyAndSetAVSAttribute(tag,attributes,3,'m',AttributeNames.i_Gender,AttributeNames.v_Masculine);
			verifyAndSetAVSAttribute(tag,attributes,3,'f',AttributeNames.i_Gender,AttributeNames.v_Feminine);
			verifyAndSetAVSAttribute(tag,attributes,3,'0',AttributeNames.i_Gender,AttributeNames.v_NA);
			verifyAndSetAVSAttribute(tag,attributes,4,'s',AttributeNames.i_Number,AttributeNames.v_Singular);
			verifyAndSetAVSAttribute(tag,attributes,4,'p',AttributeNames.i_Number,AttributeNames.v_Plural);
			verifyAndSetAVSAttribute(tag,attributes,5,'n',AttributeNames.i_Case,AttributeNames.v_Nominative);
			verifyAndSetAVSAttribute(tag,attributes,5,'g',AttributeNames.i_Case,AttributeNames.v_Genitive);
			verifyAndSetAVSAttribute(tag,attributes,5,'d',AttributeNames.i_Case,AttributeNames.v_Dative);
			verifyAndSetAVSAttribute(tag,attributes,5,'a',AttributeNames.i_Case,AttributeNames.v_Accusative);
			verifyAndSetAVSAttribute(tag,attributes,5,'v',AttributeNames.i_Case,AttributeNames.v_Vocative);
			verifyAndSetAVSAttribute(tag,attributes,5,'l',AttributeNames.i_Case,AttributeNames.v_Locative);
			verifyAndSetAVSAttribute(tag,attributes,5,'0',AttributeNames.i_Case,AttributeNames.v_NA);
			verifyAndSetAVSAttribute(tag,attributes,6,'v',AttributeNames.i_Order,AttributeNames.v_Ones);
			verifyAndSetAVSAttribute(tag,attributes,6,'p',AttributeNames.i_Order,AttributeNames.v_Teens);
			verifyAndSetAVSAttribute(tag,attributes,6,'d',AttributeNames.i_Order,AttributeNames.v_Tens);
			verifyAndSetAVSAttribute(tag,attributes,6,'s',AttributeNames.i_Order,AttributeNames.v_Hundreds);
			verifyAndSetAVSAttribute(tag,attributes,6,'t',AttributeNames.i_Order,AttributeNames.v_Thousands);
			verifyAndSetAVSAttribute(tag,attributes,6,'m',AttributeNames.i_Order,AttributeNames.v_Millions);
			verifyAndSetAVSAttribute(tag,attributes,6,'r',AttributeNames.i_Order,AttributeNames.v_Billions);
			break;

		case 'i':
			attributes.addAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Interjection);

			verifyAndSetAVSAttribute(tag,attributes,1,'s',AttributeNames.i_Uzbuuve,AttributeNames.v_Vienkaarshs);
			verifyAndSetAVSAttribute(tag,attributes,1,'c',AttributeNames.i_Uzbuuve,AttributeNames.v_Salikts);
			break;

		case 'q':
			attributes.addAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Particle);

			verifyAndSetAVSAttribute(tag,attributes,1,'s',AttributeNames.i_Uzbuuve,AttributeNames.v_Vienkaarshs);
			verifyAndSetAVSAttribute(tag,attributes,1,'c',AttributeNames.i_Uzbuuve,AttributeNames.v_Salikts);
			break;

		case 'x':
			attributes.addAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Residual);
			verifyAndSetAVSAttribute(tag,attributes,1,'f',AttributeNames.i_ResidualType,AttributeNames.v_Foreign);
			verifyAndSetAVSAttribute(tag,attributes,1,'t',AttributeNames.i_ResidualType,AttributeNames.v_Typo);
			verifyAndSetAVSAttribute(tag,attributes,1,'n',AttributeNames.i_ResidualType,AttributeNames.v_Number);
			verifyAndSetAVSAttribute(tag,attributes,1,'o',AttributeNames.i_ResidualType,AttributeNames.v_Ordinal);
			verifyAndSetAVSAttribute(tag,attributes,1,'u',AttributeNames.i_ResidualType,AttributeNames.v_URI);
			break;

		case 'y':
			attributes.addAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Abbreviation);
			break;

		case 'z':
			attributes.addAttribute(AttributeNames.i_PartOfSpeech, AttributeNames.v_Punctuation);
			verifyAndSetAVSAttribute(tag,attributes,1,'c',AttributeNames.i_PieturziimesTips,AttributeNames.v_Komats);
			verifyAndSetAVSAttribute(tag,attributes,1,'q',AttributeNames.i_PieturziimesTips,AttributeNames.v_Peedinja);
			verifyAndSetAVSAttribute(tag,attributes,1,'s',AttributeNames.i_PieturziimesTips,AttributeNames.v_Punkts);
			verifyAndSetAVSAttribute(tag,attributes,1,'b',AttributeNames.i_PieturziimesTips,AttributeNames.v_Iekava);
			verifyAndSetAVSAttribute(tag,attributes,1,'d',AttributeNames.i_PieturziimesTips,AttributeNames.v_Domuziime);
			verifyAndSetAVSAttribute(tag,attributes,1,'o',AttributeNames.i_PieturziimesTips,AttributeNames.v_Kols);
			verifyAndSetAVSAttribute(tag,attributes,1,'x',AttributeNames.i_PieturziimesTips,AttributeNames.v_Cita);
			break;
		}

		return attributes;
	}

	// Pārceltas no klases PrologWrapper; jo tām atšķirībā no pārējā PrologWrapper nevajag
	// konstruktorā ielasīt leksikonu.

	/**
	 * Converts Kamols-style markup to Prolog list.
	 */
	public static String charsToPrologList(String chars) {
		StringBuilder sb = new StringBuilder(chars.length()*2+1);
		charsToPrologList(chars, sb);
		return sb.toString();
	}

	/**
	 * Converts Kamols-style markup to Prolog list.
	 */
	public static void charsToPrologList(String chars, StringBuilder sb) {

		sb.append('[');
		for (int i = 0; i < chars.length(); i++) {
			if (i > 0)
				sb.append(',');

			//FIXME - ne īstā vieta kristīnes marķējuma loģikai
			//FIXME - aizvākt visas anaforas prom. /Lauma
			if ((chars.startsWith("p") && i == 7) // elements, kurš ir kā saraksts no viena elem jādod
					|| (chars.startsWith("s") && i == 4)
					|| (chars.startsWith("m") && i == 6)  )
				sb.append("[" + chars.charAt(i) + "]");
			else sb.append(chars.charAt(i));
		}
		if ((chars.startsWith("p") && chars.length() < 8) ) // tagi tagad saīsināti, compatibility ar veco čunkeri
			sb.append(",[0]");
		sb.append(']');
	}

	/**
	 * Converts Word object to Prolog format necessary for chunker (A-table
	 * record).
	 * @param word			Word to be converted.
	 * @param toolgenerated	how the source for this word should be identified
	 * 						- 'tool' or 'guess'/'dict'.
	 * 						Nobody remembers the practical consequences. :)
	 * 						Probably this is used, when deciding whether to
	 * 						delete these records from A-table before rechunking.
	 * @return	transformed result.
	 */
	public static String wordToChunkerFormat(Word word, boolean toolgenerated) {
		if (!word.isRecognized())
			return ("[]");

		StringBuilder sb = new StringBuilder();
		sb.append('[');

		if (word.getCorrectWordform() != null) {
			wordformToChunkerFormat(word.getToken(), toolgenerated, sb, word.getCorrectWordform());
		} else
			for (Wordform vf : word.wordforms) {
				if (sb.length() > 1)
					sb.append(',');
				wordformToChunkerFormat(word.getToken(), toolgenerated, sb, vf);
			}

		sb.append(']');

		return sb.toString();
	}

	private static void wordformToChunkerFormat(String token,
			boolean toolgenerated, StringBuilder sb, Wordform vf) {
		String kamolsMarkup = vf.getTag();
		sb.append('[');
		sb.append("'").append(prologEscape(token)).append("',");
		if (kamolsMarkup != null)
			MarkupConverter.charsToPrologList(kamolsMarkup, sb);
		else sb.append("[]");
		sb.append(",'").append(prologEscape(vf.getValue(AttributeNames.i_Lemma))).append("',");
		sb.append(toolgenerated ? "tool" : (vf.isMatchingStrong(AttributeNames.i_Source, "minējums pēc galotnes") ? "guess" : "dict"));
		sb.append(",'").append(prologEscape(vf.getValue("Nozīme 1"))).append("'");
		sb.append(']');
	}

	/**
	 * Escape string in Prolog style.
	 */
	public static String prologEscape(String s) {
		return s != null ? s.replaceAll("\\'", "\\\\'") : null;
	}

}


/**
 * Copyright (C) 2014-2019 Philip Helger (www.helger.com)
 * philip[at]helger[dot]com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.helger.genericode.builder;

import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;

import com.helger.jaxb.builder.JAXBReaderBuilder;

/**
 * A reader builder for Genericode documents.
 *
 * @author Philip Helger
 * @param <JAXBTYPE>
 *        The Genericode implementation class to be read
 */
@NotThreadSafe
public class GenericodeReader <JAXBTYPE> extends JAXBReaderBuilder <JAXBTYPE, GenericodeReader <JAXBTYPE>>
{
  public GenericodeReader (@Nonnull final EGenericodeDocumentType eDocType, @Nonnull final Class <JAXBTYPE> aImplClass)
  {
    super (eDocType, aImplClass);
  }

  /**
   * Create a reader builder for com.helger.genericode.v04.CodeListDocument.
   *
   * @return The builder and never null
   */
  @Nonnull
  public static GenericodeReader <com.helger.genericode.v04.CodeListDocument> gc04CodeList ()
  {
    return new GenericodeReader<> (EGenericodeDocumentType.GC04_CODE_LIST,
                                   com.helger.genericode.v04.CodeListDocument.class);
  }

  /**
   * Create a reader builder for com.helger.genericode.v04.CodeListSetDocument.
   *
   * @return The builder and never null
   */
  @Nonnull
  public static GenericodeReader <com.helger.genericode.v04.CodeListSetDocument> gc04CodeListSet ()
  {
    return new GenericodeReader<> (EGenericodeDocumentType.GC04_CODE_LIST_SET,
                                   com.helger.genericode.v04.CodeListSetDocument.class);
  }

  /**
   * Create a reader builder for com.helger.genericode.v04.ColumnSetDocument.
   *
   * @return The builder and never null
   */
  @Nonnull
  public static GenericodeReader <com.helger.genericode.v04.ColumnSetDocument> gc04ColumnSet ()
  {
    return new GenericodeReader<> (EGenericodeDocumentType.GC04_COLUMN_SET,
                                   com.helger.genericode.v04.ColumnSetDocument.class);
  }

  /**
   * Create a reader builder for com.helger.genericode.v10.CodeListDocument.
   *
   * @return The builder and never null
   */
  @Nonnull
  public static GenericodeReader <com.helger.genericode.v10.CodeListDocument> gc10CodeList ()
  {
    return new GenericodeReader<> (EGenericodeDocumentType.GC10_CODE_LIST,
                                   com.helger.genericode.v10.CodeListDocument.class);
  }

  /**
   * Create a reader builder for com.helger.genericode.v10.CodeListSetDocument.
   *
   * @return The builder and never null
   */
  @Nonnull
  public static GenericodeReader <com.helger.genericode.v10.CodeListSetDocument> gc10CodeListSet ()
  {
    return new GenericodeReader<> (EGenericodeDocumentType.GC10_CODE_LIST_SET,
                                   com.helger.genericode.v10.CodeListSetDocument.class);
  }

  /**
   * Create a reader builder for com.helger.genericode.v10.ColumnSetDocument.
   *
   * @return The builder and never null
   */
  @Nonnull
  public static GenericodeReader <com.helger.genericode.v10.ColumnSetDocument> gc10ColumnSet ()
  {
    return new GenericodeReader<> (EGenericodeDocumentType.GC10_COLUMN_SET,
                                   com.helger.genericode.v10.ColumnSetDocument.class);
  }
}