From a18e52a599207693b6b3306173d6a5695a111a37 Mon Sep 17 00:00:00 2001 From: Luka Date: Tue, 19 Jun 2018 09:15:37 +0200 Subject: [PATCH] Project copied --- .gitignore | 160 + Corpus Analyzer.iml | 28 + pom.xml | 122 + src/main/java/META-INF/MANIFEST.MF | 3 + src/main/java/alg/Common.java | 15 + src/main/java/alg/XML_processing.java | 794 + src/main/java/alg/inflectedJOS/ForkJoin.java | 67 + .../alg/inflectedJOS/InflectedJOSCount.java | 170 + .../java/alg/inflectedJOS/WordFormation.java | 131 + src/main/java/alg/ngram/ForkJoin.java | 62 + src/main/java/alg/ngram/Ngrams.java | 204 + src/main/java/alg/word/ForkJoin.java | 62 + src/main/java/alg/word/WordCount.java | 167 + src/main/java/alg/word/WordLevel.java | 112 + src/main/java/data/AnalysisLevel.java | 17 + src/main/java/data/CalculateFor.java | 43 + src/main/java/data/Corpus.java | 163 + src/main/java/data/CorpusType.java | 25 + .../java/data/Enums/InflectedJosTypes.java | 12 + src/main/java/data/Enums/Msd.java | 68 + .../data/Enums/WordLevelDefaultValues.java | 55 + src/main/java/data/Enums/WordLevelType.java | 16 + .../java/data/Enums/solar/SolarFilters.java | 57 + src/main/java/data/Filter.java | 144 + src/main/java/data/GigafidaJosWordType.java | 71 + src/main/java/data/GigafidaTaxonomy.java | 76 + src/main/java/data/GosTaxonomy.java | 85 + src/main/java/data/Sentence.java | 56 + src/main/java/data/Settings.java | 16 + src/main/java/data/Statistics.java | 299 + src/main/java/data/StatisticsNew.java | 409 + src/main/java/data/Tax.java | 175 + src/main/java/data/Taxonomy.java | 171 + src/main/java/data/Validation.java | 53 + src/main/java/data/Word.java | 141 + src/main/java/gui/CharacterAnalysisTab.java | 454 + src/main/java/gui/CorpusTab.java | 517 + src/main/java/gui/FiltersForSolar.java | 187 + src/main/java/gui/GUIController.java | 150 + src/main/java/gui/Messages.java | 74 + src/main/java/gui/OneWordAnalysisTab.java | 389 + src/main/java/gui/SelectedFiltersPane.java | 18 + src/main/java/gui/StringAnalysisTabNew2.java | 511 + src/main/java/gui/ValidationUtil.java | 77 + src/main/java/gui/WordFormationTab.java | 208 + src/main/java/gui/WordLevelTab.java | 207 + src/main/java/manifest/META-INF/MANIFEST.MF | 3 + src/main/java/util/ByteUtils.java | 25 + src/main/java/util/Combinations.java | 46 + src/main/java/util/Export.java | 267 + src/main/java/util/Key.java | 31 + src/main/java/util/TimeWatch.java | 63 + src/main/java/util/Util.java | 225 + src/main/java/util/db/RDB.java | 132 + .../resources/GOS_small/TEI_GOS_small.xml | 68720 ++++++++++++++++ .../resources/GOS_tax_test/GOS_tax_test.xml | 524 + src/main/resources/GUI.fxml | 133 + src/main/resources/Gigafida_minimal/gfmin.xml | 237 + ...lema_0-gram_0-skip_14.05.2018_06.34.13.csv | 70 + ...lema_0-gram_0-skip_14.05.2018_06.37.50.csv | 390 + ...lema_0-gram_0-skip_14.05.2018_06.38.17.csv | 1147 + ...lema_1-gram_0-skip_31.01.2018_05.11.26.csv | 455 + ...lema_2-gram_1-skip_31.01.2018_05.11.33.csv | 1160 + ...nica_1-gram_0-skip_25.01.2018_06.27.41.csv | 512 + ...ličnica_2-gram_0-skip_20.01.2018_01.27.csv | 623 + ...ličnica_3-gram_0-skip_20.01.2018_01.27.csv | 572 + .../resources/Gigafida_subset/F0012405.xml | 350 + .../resources/Gigafida_subset/F0016316.xml | 367 + .../resources/Gigafida_subset/F0018194.xml | 336 + .../resources/Gigafida_subset/F0026709.xml | 367 + .../resources/Gigafida_subset/F0030361.xml | 365 + .../Gigafida_subset/nested/F0036980.xml | 356 + .../Gigafida_subset/nested/F0037258.xml | 408 + .../Gigafida_subset/nested/F0037544.xml | 391 + .../Gigafida_subset/nested/F0038754.xml | 355 + .../Gigafida_subset/nested/F0038920.xml | 402 + src/main/resources/Lists/prefixes.txt | 18 + src/main/resources/Lists/suffixes.txt | 7 + .../resources/gui/CharacterAnalysisTab.fxml | 54 + src/main/resources/gui/CorpusTab.fxml | 32 + src/main/resources/gui/FiltersForSolar.fxml | 30 + .../resources/gui/OneWordAnalysisTab.fxml | 56 + .../resources/gui/SelectedFiltersPane.fxml | 13 + .../resources/gui/StringAnalysisTabNew2.fxml | 105 + src/main/resources/gui/WordFormationTab.fxml | 25 + src/main/resources/gui/WordLevelTab.fxml | 25 + src/main/resources/log4j2.xml | 22 + src/test/java/Common.java | 85 + src/test/java/CorpusTests.java | 42 + src/test/java/DBTest.java | 66 + src/test/java/NgramTests.java | 334 + src/test/java/WordFormationTest.java | 51 + src/test/java/WordLevelTest.java | 15 + src/test/java/WordTest.java | 39 + 94 files changed, 87092 insertions(+) create mode 100644 .gitignore create mode 100644 Corpus Analyzer.iml create mode 100644 pom.xml create mode 100644 src/main/java/META-INF/MANIFEST.MF create mode 100644 src/main/java/alg/Common.java create mode 100644 src/main/java/alg/XML_processing.java create mode 100644 src/main/java/alg/inflectedJOS/ForkJoin.java create mode 100644 src/main/java/alg/inflectedJOS/InflectedJOSCount.java create mode 100644 src/main/java/alg/inflectedJOS/WordFormation.java create mode 100644 src/main/java/alg/ngram/ForkJoin.java create mode 100644 src/main/java/alg/ngram/Ngrams.java create mode 100644 src/main/java/alg/word/ForkJoin.java create mode 100644 src/main/java/alg/word/WordCount.java create mode 100644 src/main/java/alg/word/WordLevel.java create mode 100644 src/main/java/data/AnalysisLevel.java create mode 100644 src/main/java/data/CalculateFor.java create mode 100644 src/main/java/data/Corpus.java create mode 100644 src/main/java/data/CorpusType.java create mode 100644 src/main/java/data/Enums/InflectedJosTypes.java create mode 100644 src/main/java/data/Enums/Msd.java create mode 100644 src/main/java/data/Enums/WordLevelDefaultValues.java create mode 100644 src/main/java/data/Enums/WordLevelType.java create mode 100644 src/main/java/data/Enums/solar/SolarFilters.java create mode 100644 src/main/java/data/Filter.java create mode 100644 src/main/java/data/GigafidaJosWordType.java create mode 100644 src/main/java/data/GigafidaTaxonomy.java create mode 100644 src/main/java/data/GosTaxonomy.java create mode 100644 src/main/java/data/Sentence.java create mode 100644 src/main/java/data/Settings.java create mode 100644 src/main/java/data/Statistics.java create mode 100644 src/main/java/data/StatisticsNew.java create mode 100644 src/main/java/data/Tax.java create mode 100644 src/main/java/data/Taxonomy.java create mode 100644 src/main/java/data/Validation.java create mode 100644 src/main/java/data/Word.java create mode 100644 src/main/java/gui/CharacterAnalysisTab.java create mode 100644 src/main/java/gui/CorpusTab.java create mode 100644 src/main/java/gui/FiltersForSolar.java create mode 100644 src/main/java/gui/GUIController.java create mode 100644 src/main/java/gui/Messages.java create mode 100755 src/main/java/gui/OneWordAnalysisTab.java create mode 100644 src/main/java/gui/SelectedFiltersPane.java create mode 100755 src/main/java/gui/StringAnalysisTabNew2.java create mode 100644 src/main/java/gui/ValidationUtil.java create mode 100644 src/main/java/gui/WordFormationTab.java create mode 100644 src/main/java/gui/WordLevelTab.java create mode 100644 src/main/java/manifest/META-INF/MANIFEST.MF create mode 100644 src/main/java/util/ByteUtils.java create mode 100644 src/main/java/util/Combinations.java create mode 100644 src/main/java/util/Export.java create mode 100644 src/main/java/util/Key.java create mode 100644 src/main/java/util/TimeWatch.java create mode 100644 src/main/java/util/Util.java create mode 100644 src/main/java/util/db/RDB.java create mode 100644 src/main/resources/GOS_small/TEI_GOS_small.xml create mode 100644 src/main/resources/GOS_tax_test/GOS_tax_test.xml create mode 100644 src/main/resources/GUI.fxml create mode 100644 src/main/resources/Gigafida_minimal/gfmin.xml create mode 100644 src/main/resources/Gigafida_subset/Besedni_nizi_Gigafida_lema_0-gram_0-skip_14.05.2018_06.34.13.csv create mode 100644 src/main/resources/Gigafida_subset/Besedni_nizi_Gigafida_lema_0-gram_0-skip_14.05.2018_06.37.50.csv create mode 100644 src/main/resources/Gigafida_subset/Besedni_nizi_Gigafida_lema_0-gram_0-skip_14.05.2018_06.38.17.csv create mode 100644 src/main/resources/Gigafida_subset/Besedni_nizi_Gigafida_lema_1-gram_0-skip_31.01.2018_05.11.26.csv create mode 100644 src/main/resources/Gigafida_subset/Besedni_nizi_Gigafida_lema_2-gram_1-skip_31.01.2018_05.11.33.csv create mode 100644 src/main/resources/Gigafida_subset/Besedni_nizi_Gigafida_različnica_1-gram_0-skip_25.01.2018_06.27.41.csv create mode 100644 src/main/resources/Gigafida_subset/Besedni_nizi_Gigafida_različnica_2-gram_0-skip_20.01.2018_01.27.csv create mode 100644 src/main/resources/Gigafida_subset/Besedni_nizi_Gigafida_različnica_3-gram_0-skip_20.01.2018_01.27.csv create mode 100644 src/main/resources/Gigafida_subset/F0012405.xml create mode 100644 src/main/resources/Gigafida_subset/F0016316.xml create mode 100644 src/main/resources/Gigafida_subset/F0018194.xml create mode 100644 src/main/resources/Gigafida_subset/F0026709.xml create mode 100644 src/main/resources/Gigafida_subset/F0030361.xml create mode 100644 src/main/resources/Gigafida_subset/nested/F0036980.xml create mode 100644 src/main/resources/Gigafida_subset/nested/F0037258.xml create mode 100644 src/main/resources/Gigafida_subset/nested/F0037544.xml create mode 100644 src/main/resources/Gigafida_subset/nested/F0038754.xml create mode 100644 src/main/resources/Gigafida_subset/nested/F0038920.xml create mode 100644 src/main/resources/Lists/prefixes.txt create mode 100644 src/main/resources/Lists/suffixes.txt create mode 100644 src/main/resources/gui/CharacterAnalysisTab.fxml create mode 100644 src/main/resources/gui/CorpusTab.fxml create mode 100644 src/main/resources/gui/FiltersForSolar.fxml create mode 100755 src/main/resources/gui/OneWordAnalysisTab.fxml create mode 100644 src/main/resources/gui/SelectedFiltersPane.fxml create mode 100755 src/main/resources/gui/StringAnalysisTabNew2.fxml create mode 100644 src/main/resources/gui/WordFormationTab.fxml create mode 100644 src/main/resources/gui/WordLevelTab.fxml create mode 100644 src/main/resources/log4j2.xml create mode 100644 src/test/java/Common.java create mode 100644 src/test/java/CorpusTests.java create mode 100644 src/test/java/DBTest.java create mode 100644 src/test/java/NgramTests.java create mode 100644 src/test/java/WordFormationTest.java create mode 100644 src/test/java/WordLevelTest.java create mode 100644 src/test/java/WordTest.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f794c26 --- /dev/null +++ b/.gitignore @@ -0,0 +1,160 @@ +# Created by .ignore support plugin (hsz.mobi) +### Maven template +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties + +# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) +!/.mvn/wrapper/maven-wrapper.jar +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries +.idea/ + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties +### Java template +# Compiled class file +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.war +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +### Eclipse template + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + + + + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk diff --git a/Corpus Analyzer.iml b/Corpus Analyzer.iml new file mode 100644 index 0000000..7483456 --- /dev/null +++ b/Corpus Analyzer.iml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..1f4b81a --- /dev/null +++ b/pom.xml @@ -0,0 +1,122 @@ + + + 4.0.0 + + thesis + corpus-analyzer + 1.2 + + + + commons-io + commons-io + 2.5 + + + org.apache.commons + commons-lang3 + 3.6 + + + com.googlecode.json-simple + json-simple + 1.1.1 + + + org.apache.commons + commons-csv + 1.4 + + + org.controlsfx + controlsfx + 8.40.13 + + + org.rocksdb + rocksdbjni + 5.7.3 + + + org.apache.logging.log4j + log4j-api + 2.9.0 + + + org.apache.logging.log4j + log4j-core + 2.9.0 + + + org.kordamp.ikonli + ikonli-fontawesome-pack + 1.9.0 + + + org.kordamp.ikonli + ikonli-javafx + 1.9.0 + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + package + + single + + + + + gui.GUIController + + + + jar-with-dependencies + + false + artifact + Corpus_Analyzer_${version} + + + + + + + com.zenjava + javafx-maven-plugin + 8.6.0 + + gui.GUIController + true + + + + create-jfxjar + package + + build-jar + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + \ No newline at end of file diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 0000000..d2c5d1f --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: gui.GUIController + diff --git a/src/main/java/alg/Common.java b/src/main/java/alg/Common.java new file mode 100644 index 0000000..5bbd0a8 --- /dev/null +++ b/src/main/java/alg/Common.java @@ -0,0 +1,15 @@ +package alg; + +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +public class Common { + public static void updateMap(Map map, K o) { + // if not in map + AtomicLong r = map.putIfAbsent(o, new AtomicLong(1)); + + // else + if (r != null) + map.get(o).incrementAndGet(); + } +} diff --git a/src/main/java/alg/XML_processing.java b/src/main/java/alg/XML_processing.java new file mode 100644 index 0000000..94c94cc --- /dev/null +++ b/src/main/java/alg/XML_processing.java @@ -0,0 +1,794 @@ +package alg; + +import static data.Enums.solar.SolarFilters.*; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.*; +import java.util.concurrent.ForkJoinPool; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.*; + +import org.apache.logging.log4j.LogManager; + +import data.*; +import gui.ValidationUtil; + +public class XML_processing { + public final static org.apache.logging.log4j.Logger logger = LogManager.getLogger(XML_processing.class); + + // public static void processCorpus(Statistics stats) { + // // we can preset the list's size, so there won't be a need to resize it + // List corpus = new ArrayList<>(Settings.CORPUS_SENTENCE_LIMIT); + // + // int i = 0; + // for (File f : Settings.corpus) { + // i++; + // readXML(f.toString(), stats); + // } + // } + + // public static void readXML(String path, Statistics stats) { + // if (stats.getCorpusType() == CorpusType.GIGAFIDA) { + // readXMLGigafida(path, stats); + // } else if (stats.getCorpusType() == CorpusType.GOS) { + // readXMLGos(path, stats); + // } else if (stats.getCorpusType() == CorpusType.SOLAR) { + // readXMLSolar(path, stats); + // } + // } + + public static void readXML(String path, StatisticsNew stats) { + if (stats.getCorpus().getCorpusType() == CorpusType.GIGAFIDA + || stats.getCorpus().getCorpusType() == CorpusType.CCKRES) { + readXMLGigafida(path, stats); + } else if (stats.getCorpus().getCorpusType() == CorpusType.GOS) { + readXMLGos(path, stats); + } else if (stats.getCorpus().getCorpusType() == CorpusType.SOLAR) { + readXMLSolar(path, stats); + } + } + + /** + * Reads and returns the value of a passed header tag or an empty string. + * E.g. title tag, for discerning the corpus' type. + * Notice: returns only the value of the first occurrence of a given tag name. + */ + public static String readXMLHeaderTag(String path, String tag) { + XMLInputFactory factory = XMLInputFactory.newInstance(); + XMLEventReader eventReader = null; + + try { + eventReader = factory.createXMLEventReader(new FileInputStream(path)); + while (eventReader.hasNext()) { + XMLEvent xmlEvent = eventReader.nextEvent(); + if (xmlEvent.isStartElement()) { + StartElement startElement = xmlEvent.asStartElement(); + String var = startElement.getName().getLocalPart(); + + if (var.equalsIgnoreCase(tag)) { + return eventReader.nextEvent().asCharacters().getData(); + } + } + } + } catch (FileNotFoundException | XMLStreamException e) { + e.printStackTrace(); + } finally { + if (eventReader != null) { + try { + eventReader.close(); + } catch (XMLStreamException e) { + logger.error("closing stream", e); + } + } + } + return ""; + } + + private static void fj(List corpus, StatisticsNew stats) { + ForkJoinPool pool = new ForkJoinPool(); + + if (stats.getFilter().getAl() == AnalysisLevel.STRING_LEVEL) { + alg.ngram.ForkJoin wc = new alg.ngram.ForkJoin(corpus, stats); + pool.invoke(wc); + } else if (stats.getFilter().getAl() == AnalysisLevel.WORD_LEVEL) { + alg.word.ForkJoin wc = new alg.word.ForkJoin(corpus, stats); + pool.invoke(wc); + } else { + // TODO: + // alg.inflectedJOS.ForkJoin wc = new alg.inflectedJOS.ForkJoin(corpus, stats); + // pool.invoke(wc); + } + } + + // public static void readXMLGos(String path, Statistics stats) { + // boolean in_word = false; + // String taksonomija = ""; + // String lemma = ""; + // String msd = ""; + // String type = stats.isGosOrthMode() ? "orth" : "norm"; // orth & norm + // + // List stavek = new ArrayList<>(); + // List corpus = new ArrayList<>(); + // String sentenceDelimiter = "seg"; + // String taxonomyPrefix = "gos."; + // + // try { + // XMLInputFactory factory = XMLInputFactory.newInstance(); + // XMLEventReader eventReader = factory.createXMLEventReader(new FileInputStream(path)); + // + // while (eventReader.hasNext()) { + // XMLEvent event = eventReader.nextEvent(); + // + // switch (event.getEventType()) { + // case XMLStreamConstants.START_ELEMENT: + // + // StartElement startElement = event.asStartElement(); + // String qName = startElement.getName().getLocalPart(); + // + // // "word" node + // if (qName.equals("w")) { + // in_word = true; + // + // if (type.equals("norm")) { + // // make sure we're looking at and not + // Iterator var = startElement.getAttributes(); + // ArrayList attributes = new ArrayList<>(); + // while (var.hasNext()) { + // attributes.add(var.next()); + // } + // + // if (attributes.contains("msd")) { + // msd = String.valueOf(startElement.getAttributeByName(QName.valueOf("msd")).getValue()); + // } else { + // msd = null; + // } + // + // if (attributes.contains("lemma")) { + // lemma = String.valueOf(startElement.getAttributeByName(QName.valueOf("lemma")).getValue()); + // } + // } + // } + // // taxonomy node + // else if (qName.equalsIgnoreCase("catRef")) { + // // there are some term nodes at the beginning that are of no interest to us + // // they differ by not having the attribute "ref", so test will equal null + // Attribute test = startElement.getAttributeByName(QName.valueOf("target")); + // + // if (test != null) { + // // keep only taxonomy properties + // taksonomija = String.valueOf(test.getValue()).replace(taxonomyPrefix, ""); + // } + // } else if (qName.equalsIgnoreCase("div")) { + // type = String.valueOf(startElement.getAttributeByName(QName.valueOf("type")).getValue()); + // + // } + // break; + // + // case XMLStreamConstants.CHARACTERS: + // Characters characters = event.asCharacters(); + // + // // "word" node value + // if (in_word) { + // if (type.equals("norm") && msd != null) { + // stavek.add(new Word(characters.getData(), lemma, msd)); + // } else { + // stavek.add(new Word(characters.getData())); + // } + // + // in_word = false; + // } + // break; + // + // case XMLStreamConstants.END_ELEMENT: + // EndElement endElement = event.asEndElement(); + // + // // parser reached end of the current sentence + // if (endElement.getName().getLocalPart().equals(sentenceDelimiter)) { + // // add sentence to corpus + // corpus.add(new Sentence(stavek, taksonomija, type)); + // // and start a new one + // stavek = new ArrayList<>(); + // + // /* Invoke Fork-Join when we reach maximum limit of + // * sentences (because we can't read everything to + // * memory) or we reach the end of the file. + // */ + // if (corpus.size() == Settings.CORPUS_SENTENCE_LIMIT || !eventReader.hasNext()) { + // fj(corpus, stats); + // // empty the current corpus, since we don't need + // // the data anymore + // corpus.clear(); + // } + // } + // + // // backup + // if (endElement.getName().getLocalPart().equalsIgnoreCase("tei")) { + // fj(corpus, stats); + // corpus.clear(); + // } + // + // break; + // } + // } + // } catch (FileNotFoundException | XMLStreamException e) { + // e.printStackTrace(); + // } + // } + + @SuppressWarnings("unused") + public static void readXMLSolar(String path, StatisticsNew stats) { + boolean in_word = false; + String lemma = ""; + String msd = ""; + + List stavek = new ArrayList<>(); + List corpus = new ArrayList<>(); + + // used for filter + Set headTags = new HashSet<>(Arrays.asList("sola", "predmet", "razred", "regija", "tip", "leto")); + Map headBlock = null; + boolean includeThisBlock = false; + + try { + XMLInputFactory factory = XMLInputFactory.newInstance(); + XMLEventReader eventReader = factory.createXMLEventReader(new FileInputStream(path)); + + while (eventReader.hasNext()) { + XMLEvent event = eventReader.nextEvent(); + + switch (event.getEventType()) { + case XMLStreamConstants.START_ELEMENT: + + StartElement startElement = event.asStartElement(); + // System.out.println(String.format("%s", startElement.toString())); + String qName = startElement.getName().getLocalPart(); + + // "word" node + if (qName.equals("w3")) { + in_word = true; + + msd = String.valueOf(startElement.getAttributeByName(QName.valueOf("msd")).getValue()); + lemma = String.valueOf(startElement.getAttributeByName(QName.valueOf("lemma")).getValue()); + } else if (qName.equals("c3")) { + String c3Content = eventReader.nextEvent().asCharacters().getData(); + + if (c3Content.equals(".") && includeThisBlock) { + // add sentence to corpus + corpus.add(new Sentence(stavek)); + // and start a new one + stavek = new ArrayList<>(); + + /* Invoke Fork-Join when we reach maximum limit of + * sentences (because we can't read everything to + * memory) or we reach the end of the file. + */ + if (corpus.size() == Settings.CORPUS_SENTENCE_LIMIT || !eventReader.hasNext()) { + fj(corpus, stats); + // empty the current corpus, since we don't need + // the data anymore + corpus.clear(); + } + } + } else if (headTags.contains(qName)) { + String tagContent = eventReader.nextEvent().asCharacters().getData(); + headBlock.put(qName, tagContent); + } else if (qName.equals("head")) { + headBlock = new HashMap<>(); + } + + break; + + case XMLStreamConstants.CHARACTERS: + Characters characters = event.asCharacters(); + + // "word" node value + if (in_word) { + stavek.add(new Word(characters.getData(), lemma, msd)); + in_word = false; + } + break; + + case XMLStreamConstants.END_ELEMENT: + EndElement endElement = event.asEndElement(); + String qNameEnd = endElement.getName().getLocalPart(); + + if (qNameEnd.equals("head")) { + // validate and set boolean + if (validateHeadBlock(headBlock, stats.getFilter().getSolarFilters())) { + includeThisBlock = true; + } + } else if (qNameEnd.equals("body")) { + // new block, reset filter status + includeThisBlock = false; + } + + // backup + if (endElement.getName().getLocalPart().equalsIgnoreCase("korpus")) { + fj(corpus, stats); + corpus.clear(); + } + + break; + } + } + } catch (FileNotFoundException | XMLStreamException e) { + e.printStackTrace(); + } + } + + /** + * @param readHeadBlock block of tags read from the corpus + * @param userSetFilter tags with values set by the user + * + * @return + */ + private static boolean validateHeadBlock(Map readHeadBlock, HashMap> userSetFilter) { + boolean pass = true; + + if (userSetFilter == null) { + return true; + } + + for (Map.Entry> filterEntry : userSetFilter.entrySet()) { + String key = filterEntry.getKey(); + HashSet valueObject = filterEntry.getValue(); + + // if (valueObject instanceof String) { + // pass = validateHeadBlockEntry(readHeadBlock, key, (String) valueObject); + // } else + if (valueObject != null) { + //noinspection unchecked + for (String value : valueObject) { + pass = validateHeadBlockEntry(readHeadBlock, key, value); + } + } + + if (!pass) { + // current head block does not include one of the set filters - not likely, but an edge case anyway + return false; + } + } + + // if it gets to this point, it passed all the filters + return true; + } + + private static boolean validateHeadBlockEntry(Map readHeadBlock, String userSetKey, String userSetValue) { + if (!readHeadBlock.keySet().contains(userSetKey)) { + // current head block does not include one of the set filters - not likely, but an edge case anyway + return false; + } else if (!readHeadBlock.get(userSetKey).equals(userSetValue)) { + // different values -> doesn't pass the filter + return false; + } + + return true; + } + + /** + * Parses XML headers for information about its taxonomy (if supported) or filters (solar) + * + * @param filepath + * @param corpusIsSplit is corpus split into multiple xml files, or are all entries grouped into one large xml file + * @param corpusType + */ + public static Object readXmlHeaderTaxonomyAndFilters(String filepath, boolean corpusIsSplit, CorpusType corpusType) { + boolean parseTaxonomy = Tax.getCorpusTypesWithTaxonomy().contains(corpusType); + // solar + Set headTags = null; + HashMap> resultFilters = new HashMap<>(); + // taxonomy corpora + HashSet resultTaxonomy = new HashSet<>(); + + String headTagName; + + if (corpusType == CorpusType.SOLAR) { + headTagName = "head"; + // used for filter + headTags = new HashSet<>(Arrays.asList(SOLA, PREDMET, RAZRED, REGIJA, TIP, LETO)); + + // init results now to avoid null pointers + headTags.forEach(f -> resultFilters.put(f, new HashSet<>())); + } else { + headTagName = "teiHeader"; + } + + XMLInputFactory factory = XMLInputFactory.newInstance(); + XMLEventReader xmlEventReader = null; + try { + xmlEventReader = factory.createXMLEventReader(new FileInputStream(filepath)); + boolean insideHeader = false; + + while (xmlEventReader.hasNext()) { + XMLEvent xmlEvent = xmlEventReader.nextEvent(); + + if (xmlEvent.isStartElement()) { + StartElement startElement = xmlEvent.asStartElement(); + String elementName = startElement.getName().getLocalPart(); + + if (elementName.equalsIgnoreCase(headTagName)) { + // if the corpus is split into files, we skip bodies + // this toggle is true when we're inside a header (next block of code executes) + // and false when we're not (skip reading unnecessary attributes) + insideHeader = true; + } + + if (insideHeader) { + if (parseTaxonomy && elementName.equalsIgnoreCase("catRef")) { + HashMap atts = extractAttributes(startElement); + String debug = ""; + + String tax = startElement.getAttributeByName(QName.valueOf("target")) + .getValue() + .replace("#", ""); + + resultTaxonomy.add(tax); + } else if (!parseTaxonomy && headTags.contains(elementName)) { + String tagContent = xmlEventReader.nextEvent().asCharacters().getData(); + resultFilters.get(elementName).add(tagContent); + } + } + } else if (xmlEvent.isEndElement() && corpusIsSplit && isEndElementEndOfHeader(xmlEvent, headTagName)) { + // if the corpus is split into multiple files, each with only one header block per file + // that means we should stop after we reach the end of the header + return parseTaxonomy ? resultTaxonomy : resultFilters; + } else if (xmlEvent.isEndElement() && !corpusIsSplit && isEndElementEndOfHeader(xmlEvent, headTagName)) { + // whole corpus in one file, so we have to continue reading in order to find all header blocks + insideHeader = false; + } + } + } catch (XMLStreamException e) { + logger.error("Streaming error", e); + return parseTaxonomy ? resultTaxonomy : resultFilters; + } catch (FileNotFoundException e) { + logger.error("File not found", e); + return parseTaxonomy ? resultTaxonomy : resultFilters; + // TODO: keep a list of files that threw this error and a dirty boolean marker -> if true, alert user + } finally { + if (xmlEventReader != null) { + try { + xmlEventReader.close(); + } catch (XMLStreamException e) { + logger.error("closing stream", e); + } + } + } + return parseTaxonomy ? resultTaxonomy : resultFilters; + } + + private static boolean isEndElementEndOfHeader(XMLEvent event, String headerTag) { + return event.asEndElement() + .getName() + .getLocalPart() + .equalsIgnoreCase(headerTag); + } + + @SuppressWarnings("Duplicates") + public static boolean readXMLGigafida(String path, StatisticsNew stats) { + boolean inWord = false; + ArrayList currentFiletaxonomy = new ArrayList<>(); + String lemma = ""; + String msd = ""; + + List sentence = new ArrayList<>(); + List corpus = new ArrayList<>(Settings.CORPUS_SENTENCE_LIMIT); // preset the list's size, so there won't be a need to resize it + String sentenceDelimiter = "s"; + + XMLEventReader eventReader = null; + try { + XMLInputFactory factory = XMLInputFactory.newInstance(); + eventReader = factory.createXMLEventReader(new FileInputStream(path)); + + while (eventReader.hasNext()) { + XMLEvent event = eventReader.nextEvent(); + + switch (event.getEventType()) { + case XMLStreamConstants.START_ELEMENT: + StartElement startElement = event.asStartElement(); + String qName = startElement.getName().getLocalPart(); + + // "word" node + if (qName.equals("w")) { + inWord = true; + + msd = String.valueOf(startElement.getAttributeByName(QName.valueOf("msd")).getValue()); + lemma = String.valueOf(startElement.getAttributeByName(QName.valueOf("lemma")).getValue()); + } + // taxonomy node + else if (qName.equalsIgnoreCase("catRef")) { + // there are some term nodes at the beginning that are of no interest to us + // they differ by not having the attribute "ref", so test will equal null + Attribute tax = startElement.getAttributeByName(QName.valueOf("target")); + + if (tax != null) { + // keep only taxonomy properties + currentFiletaxonomy.add(String.valueOf(tax.getValue()).replace("#", "")); + } + } + break; + + case XMLStreamConstants.CHARACTERS: + Characters characters = event.asCharacters(); + + // "word" node value + if (inWord) { + String word = characters.getData(); + sentence.add(new Word(word, lemma, msd)); + inWord = false; + } + break; + + case XMLStreamConstants.END_ELEMENT: + EndElement endElement = event.asEndElement(); + + String var = endElement.getName().getLocalPart(); + String debug = ""; + + // parser reached end of the current sentence + if (endElement.getName().getLocalPart().equals(sentenceDelimiter)) { + // add sentence to corpus if it passes filters + sentence = runFilters(sentence, stats.getFilter()); + + if (!ValidationUtil.isEmpty(sentence)) { + corpus.add(new Sentence(sentence)); + } + + // and start a new one + sentence = new ArrayList<>(); + + /* Invoke Fork-Join when we reach maximum limit of + * sentences (because we can't read everything to + * memory) or we reach the end of the file. + */ + if (corpus.size() == Settings.CORPUS_SENTENCE_LIMIT || !eventReader.hasNext()) { + fj(corpus, stats); + // empty the current corpus, since we don't need the data anymore + corpus.clear(); + + // TODO: if (stats.isUseDB()) { + // stats.storeTmpResultsToDB(); + // } + } + } else if (endElement.getName().getLocalPart().equals("teiHeader")) { + // before proceeding to read this file, make sure that taxonomy filters are a match + + if (!ValidationUtil.isEmpty(stats.getFilter().getTaxonomy())) { + currentFiletaxonomy.retainAll(stats.getFilter().getTaxonomy()); // intersection + + if (currentFiletaxonomy.isEmpty()) { + // taxonomies don't match so stop + return false; + } + } + } + + // fallback + else if (endElement.getName().getLocalPart().equalsIgnoreCase("tei")) { + fj(corpus, stats); + corpus.clear(); + + // TODO: if (stats.isUseDB()) { + // stats.storeTmpResultsToDB(); + // } + } + + break; + } + } + } catch (FileNotFoundException | XMLStreamException e) { + e.printStackTrace(); + } finally { + if (eventReader != null) { + try { + eventReader.close(); + } catch (XMLStreamException e) { + logger.error("closing stream", e); + } + } + } + + return true; + } + + @SuppressWarnings("Duplicates") + public static boolean readXMLGos(String path, StatisticsNew stats) { + boolean inWord = false; + boolean inOrthDiv = false; + boolean computeForOrth = stats.getCorpus().isGosOrthMode(); + ArrayList currentFiletaxonomy = new ArrayList<>(); + String lemma = ""; + String msd = ""; + + List sentence = new ArrayList<>(); + List corpus = new ArrayList<>(Settings.CORPUS_SENTENCE_LIMIT); // preset the list's size, so there won't be a need to resize it + String sentenceDelimiter = "seg"; + + String gosType = stats.getFilter().hasMsd() ? "norm" : "orth"; // orth & norm + + XMLEventReader eventReader = null; + + boolean includeFile = true; + + try { + XMLInputFactory factory = XMLInputFactory.newInstance(); + eventReader = factory.createXMLEventReader(new FileInputStream(path)); + + while (eventReader.hasNext()) { + XMLEvent event = eventReader.nextEvent(); + // System.out.print(String.format("%s", event.toString().replaceAll("\\['http://www.tei-c.org/ns/1.0'\\]::", ""))); + + switch (event.getEventType()) { + case XMLStreamConstants.START_ELEMENT: + StartElement startElement = event.asStartElement(); + String qName = startElement.getName().getLocalPart(); + + if (qName.equals("div")) { + HashMap atts = extractAttributes(startElement); + + if (atts.keySet().contains("type")) { + inOrthDiv = atts.get("type").equals("orth"); + } + } + + // "word" node + if (qName.equals("w")) { + // check that it's not a type + HashMap atts = extractAttributes(startElement); + + if (!atts.containsKey("type")) { + inWord = true; + + if (atts.containsKey("msd")) { + msd = atts.get("msd"); + + } + if (atts.containsKey("lemma")) { + lemma = atts.get("lemma"); + } + // + // if (!inOrthDiv) { + // msd = String.valueOf(startElement.getAttributeByName(QName.valueOf("msd")).getValue()); + // lemma = String.valueOf(startElement.getAttributeByName(QName.valueOf("lemma")).getValue()); + // } + } + + // } + } + // taxonomy node + else if (qName.equalsIgnoreCase("catRef")) { + // there are some term nodes at the beginning that are of no interest to us + // they differ by not having the attribute "ref", so test will equal null + Attribute tax = startElement.getAttributeByName(QName.valueOf("target")); + + if (tax != null) { + // keep only taxonomy properties + currentFiletaxonomy.add(String.valueOf(tax.getValue())); + } + } else if (qName.equalsIgnoreCase("div")) { + gosType = String.valueOf(startElement.getAttributeByName(QName.valueOf("type")).getValue()); + } + break; + + case XMLStreamConstants.CHARACTERS: + // "word" node value + if (inWord) { + Characters characters = event.asCharacters(); + if (gosType.equals("norm") && msd != null) { + sentence.add(new Word(characters.getData(), lemma, msd)); + } else { + sentence.add(new Word(characters.getData())); + } + + inWord = false; + } + break; + + case XMLStreamConstants.END_ELEMENT: + EndElement endElement = event.asEndElement(); + + // parser reached end of the current sentence + if (endElement.getName().getLocalPart().equals(sentenceDelimiter)) { + // add sentence to corpus if it passes filters + boolean saveSentence = computeForOrth == inOrthDiv; + + if (includeFile && saveSentence && !ValidationUtil.isEmpty(sentence)) { + sentence = runFilters(sentence, stats.getFilter()); + corpus.add(new Sentence(sentence)); + } + + // and start a new one + sentence = new ArrayList<>(); + + /* Invoke Fork-Join when we reach maximum limit of + * sentences (because we can't read everything to + * memory) or we reach the end of the file. + */ + if (corpus.size() == Settings.CORPUS_SENTENCE_LIMIT || !eventReader.hasNext()) { + fj(corpus, stats); + // empty the current corpus, since we don't need + // the data anymore + corpus.clear(); + } + } else if (endElement.getName().getLocalPart().equals("teiHeader")) { + // before proceeding to read this file, make sure that taxonomy filters are a match + if (!ValidationUtil.isEmpty(stats.getFilter().getTaxonomy())) { + currentFiletaxonomy.retainAll(stats.getFilter().getTaxonomy()); // intersection + + // disregard this entry if taxonomies don't match + includeFile = !currentFiletaxonomy.isEmpty(); + + currentFiletaxonomy = new ArrayList<>(); + } + } + + // backup + else if (endElement.getName().getLocalPart().equalsIgnoreCase("tei")) { + fj(corpus, stats); + corpus.clear(); + } + + break; + } + } + } catch (FileNotFoundException | XMLStreamException e) { + e.printStackTrace(); + } finally { + if (eventReader != null) { + try { + eventReader.close(); + } catch (XMLStreamException e) { + logger.error("closing stream", e); + } catch (Exception e) { + logger.error("general error", e); + } + } + } + + return true; + } + + /** + * Runs the sentence through some filters, so we don't do calculations when unnecessary. + * Filters: + *
    + *
  1. Ngrams: omit sentences that are shorter than the ngram value (e.g. 3 gram of a single word sentence)
  2. + *
  3. Letter ngrams: omit words that are shorter than the specified string length (e.g. combinations of 3 letters when the word consists of only 2 letters)
  4. + *
+ * + * @return Empty sentence (if fails 1.) or a sentence with some words removed (2.) + */ + private static List runFilters(List sentence, Filter filter) { + if (filter.getAl() == AnalysisLevel.STRING_LEVEL) { + // ngram level: if not 0 must be less than or equal to number of words in this sentence. + if (filter.getNgramValue() > 0 && filter.getNgramValue() > sentence.size()) { + return null; + } + + // if we're calculating values for letters, omit words that are shorter than string length + if (filter.getNgramValue() == 0) { + sentence.removeIf(w -> (filter.getCalculateFor() == CalculateFor.WORD && w.getWord().length() < filter.getStringLength()) + || (filter.getCalculateFor() == CalculateFor.LEMMA && w.getLemma().length() < filter.getStringLength())); + } + } + + return sentence; + } + + private static HashMap extractAttributes(StartElement se) { + Iterator attributesIt = se.getAttributes(); + HashMap atts = new HashMap<>(); + + while (attributesIt.hasNext()) { + Attribute a = (Attribute) attributesIt.next(); + atts.put(a.getName().getLocalPart(), a.getValue()); + } + + return atts; + } +} diff --git a/src/main/java/alg/inflectedJOS/ForkJoin.java b/src/main/java/alg/inflectedJOS/ForkJoin.java new file mode 100644 index 0000000..e480b76 --- /dev/null +++ b/src/main/java/alg/inflectedJOS/ForkJoin.java @@ -0,0 +1,67 @@ +package alg.inflectedJOS; + +import java.util.List; +import java.util.concurrent.RecursiveAction; + +import data.Sentence; +import data.Statistics; + +public class ForkJoin extends RecursiveAction { + private static final long serialVersionUID = -1260951004477299634L; + + private static final int ACCEPTABLE_SIZE = 1000; + private List corpus; + private Statistics stats; + private int start; + private int end; + + + /** + * Constructor for subproblems. + */ + private ForkJoin(List corpus, int start, int end, Statistics stats) { + this.corpus = corpus; + this.start = start; + this.end = end; + this.stats = stats; + } + + /** + * Default constructor for the initial problem + */ + public ForkJoin(List corpus, Statistics stats) { + this.corpus = corpus; + this.start = 0; + this.end = corpus.size(); + this.stats = stats; + } + + private void computeDirectly() { + List subCorpus = corpus.subList(start, end); + + if (stats.isTaxonomySet()) { + InflectedJOSCount.calculateForAll(subCorpus, stats, stats.getInflectedJosTaxonomy()); + } else { + InflectedJOSCount.calculateForAll(subCorpus, stats, null); + } + } + + @Override + protected void compute() { + int subCorpusSize = end - start; + + if (subCorpusSize < ACCEPTABLE_SIZE) { + computeDirectly(); + } else { + int mid = start + subCorpusSize / 2; + ForkJoin left = new ForkJoin(corpus, start, mid, stats); + ForkJoin right = new ForkJoin(corpus, mid, end, stats); + + // fork (push to queue)-> compute -> join + left.fork(); + right.fork(); + left.join(); + right.join(); + } + } +} diff --git a/src/main/java/alg/inflectedJOS/InflectedJOSCount.java b/src/main/java/alg/inflectedJOS/InflectedJOSCount.java new file mode 100644 index 0000000..7d40a68 --- /dev/null +++ b/src/main/java/alg/inflectedJOS/InflectedJOSCount.java @@ -0,0 +1,170 @@ +package alg.inflectedJOS; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import alg.Common; +import data.Sentence; +import data.Statistics; +import data.StatisticsNew; +import data.Word; + +public class InflectedJOSCount { + + public static HashMap>> indices; + + // static { + // // calculate all possible combinations of indices we will substitute with a '-' for substring statistics + // indices = new HashMap<>(); + // for (int i = 5; i <= 8; i++) { + // indices.put(i, calculateCombinations(i)); + // } + // } + // + // private static List calculateCombinations(int i) { + // int arr[] = {1, 2, 3, 4, 5}; + // int r = 3; + // int n = arr.length; + // ArrayList> result = new ArrayList<>(); + // + // return printCombination(arr, n, r); + // } + // + // /* arr[] ---> Input Array + // data[] ---> Temporary array to store current combination + // start & end ---> Staring and Ending indexes in arr[] + // index ---> Current index in data[] + // r ---> Size of a combination to be printed */ + // static void combinationUtil(int arr[], int data[], int start, + // int end, int index, int r, ArrayList> result) { + // // Current combination is ready to be printed, print it + // ArrayList tmpResult = new ArrayList<>(); + // + // if (index == r) { + // ArrayList tmpResult = new ArrayList<>(); + // for (int j = 0; j < r; j++) + // System.out.print(data[j] + " "); + // System.out.println(""); + // return; + // } + // + // // replace index with all possible elements. The condition + // // "end-i+1 >= r-index" makes sure that including one element + // // at index will make a combination with remaining elements + // // at remaining positions + // for (int i = start; i <= end && end - i + 1 >= r - index; i++) { + // data[index] = arr[i]; + // combinationUtil(arr, data, i + 1, end, index + 1, r); + // } + // } + // + // // The main function that prints all combinations of size r + // // in arr[] of size n. This function mainly uses combinationUtil() + // static void printCombination(int arr[], int n, int r) { + // // A temporary array to store all combination one by one + // int data[] = new int[r]; + // + // // Print all combination using temprary array 'data[]' + // combinationUtil(arr, data, 0, n - 1, 0, r); + // } + + // public static void calculateForAll(List corpus, Statistics stats, String taxonomy) { + // for (Sentence s : corpus) { + // // disregard if wrong taxonomy + // if (!(s.getTaxonomy().startsWith(taxonomy))) { + // continue; + // } + // + // calculateCommon(s, stats.result); + // + // for (Word word : s.getWords()) { + // // skip if current word is not inflected + // if (!(word.getMsd().length() > 0)) { + // continue; + // } + // + // String msd = word.getMsd(); + // + // StringBuilder entry = new StringBuilder(msd.charAt(0) + StringUtils.repeat('-', (msd.length() - 1))); + // + // for (int i = 1; i < msd.length(); i++) { + // entry.setCharAt(i, msd.charAt(i)); + // Common.updateMap(stats.result, entry.toString()); + // entry.setCharAt(i, '-'); + // } + // } + // } + // } + + // public static void calculateForAll(List corpus, Statistics stats) { + // for (Sentence s : corpus) { + // for (Word word : s.getWords()) { + // if (!(word.getMsd().length() > 0)) { + // continue; + // } + // + // String msd = word.getMsd(); + // + // StringBuilder entry = new StringBuilder(msd.charAt(0) + StringUtils.repeat('-', (msd.length() - 1))); + // + // for (int i = 1; i < msd.length(); i++) { + // entry.setCharAt(i, msd.charAt(i)); + // Common.updateMap(stats.result, entry.toString()); + // entry.setCharAt(i, '-'); + // } + // } + // } + // } + + static void calculateForAll(List corpus, Statistics stats, String taxonomy) { + for (Sentence s : corpus) { + // disregard if wrong taxonomy + if (taxonomy != null && !(s.getTaxonomy().startsWith(taxonomy))) { + continue; + } + + for (Word word : s.getWords()) { + // skip if current word is not inflected + if (!(word.getMsd().length() > 0)) { + continue; + } + + String msd = word.getMsd(); + + StringBuilder entry = new StringBuilder(msd.charAt(0) + StringUtils.repeat('-', (msd.length() - 1))); + + for (int i = 1; i < msd.length(); i++) { + entry.setCharAt(i, msd.charAt(i)); + Common.updateMap(stats.result, entry.toString()); + entry.setCharAt(i, '-'); + } + } + } + } + + public static void calculateForAll(List corpus, StatisticsNew stats, String taxonomy) { + for (Sentence s : corpus) { + + for (Word word : s.getWords()) { + // skip if current word is not inflected + // // TODO: if has defined msd and is of correct type (create a set) + // if (!(word.getMsd().length() > 0)) { + // continue; + // } + + String msd = word.getMsd(); + + StringBuilder entry = new StringBuilder(msd.charAt(0) + StringUtils.repeat('-', (msd.length() - 1))); + + for (int i = 1; i < msd.length(); i++) { + entry.setCharAt(i, msd.charAt(i)); + stats.updateResults(entry.toString()); + entry.setCharAt(i, '-'); + } + } + } + } +} diff --git a/src/main/java/alg/inflectedJOS/WordFormation.java b/src/main/java/alg/inflectedJOS/WordFormation.java new file mode 100644 index 0000000..f3c57bf --- /dev/null +++ b/src/main/java/alg/inflectedJOS/WordFormation.java @@ -0,0 +1,131 @@ +package alg.inflectedJOS; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; + +import data.Enums.InflectedJosTypes; +import data.StatisticsNew; +import gui.ValidationUtil; +import util.Combinations; + +// adapted from http://www.geeksforgeeks.org/print-all-possible-combinations-of-r-elements-in-a-given-array-of-size-n/ +public class WordFormation { + private static HashMap josTypeResult; + private static Object[][] tmpResults; + + private static HashMap>> indices; + + static { + indices = new HashMap<>(); + + for (int i = 4; i <= 8; i++) { + indices.put(i, Combinations.generateIndices(i)); + } + } + + public static void calculateStatistics(StatisticsNew stat) { + Map result = stat.getResult(); + + // 1. filter - keep only inflected types + result.keySet().removeIf(x -> !InflectedJosTypes.inflectedJosTypes.contains(x.charAt(0))); + + // 2. for each inflected type get all possible subcombinations + for (Character josChar : InflectedJosTypes.inflectedJosTypes) { + josTypeResult = new HashMap<>(); + + // filter out results for a single word type + Map singleTypeResults = result.entrySet().stream() + .filter(x -> x.getKey().charAt(0) == josChar) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + if (ValidationUtil.isEmpty(singleTypeResults)) { + continue; + } + + // get all possible indices combos for a msd of this length + // HashSet> indicesCombos = indices.get() + //Combinations.generateIndices(singleTypeResults.keySet().stream().findFirst().get().length()); + + for (Map.Entry e : singleTypeResults.entrySet()) { + int l = e.getKey().length(); + + for (HashSet indicesCombo : indices.get(e.getKey().length())) { + updateResults(mask(e.getKey(), indicesCombo), e.getValue().longValue()); + } + } + + resultsMapToArray(singleTypeResults.values().stream().mapToLong(Number::longValue).sum()); + } + + stat.setResultCustom(tmpResults); + } + + private static String mask(String word, HashSet indicesCombo) { + StringBuilder sb = new StringBuilder(); + + sb.append(word.charAt(0)); + for (int i = 1; i < word.length(); i++) { + sb.append(indicesCombo.contains(i) ? word.charAt(i) : "."); + } + + return sb.toString(); + } + + + private static void updateResults(String s, Long nOfOccurences) { + // if not in map add + Long r = josTypeResult.putIfAbsent(s, nOfOccurences); + + // else update + if (r != null) { + josTypeResult.put(s, josTypeResult.get(s) + nOfOccurences); + } + } + + private static void resultsMapToArray(Long totalValue) { + Double total = totalValue * 1.0; + Object[][] josTypeResultArray = new Object[josTypeResult.size()][3]; + + int i = 0; + for (Map.Entry e : josTypeResult.entrySet()) { + josTypeResultArray[i][0] = e.getKey(); + josTypeResultArray[i][1] = e.getValue(); + josTypeResultArray[i][2] = e.getValue() / total; + + if (e.getValue() > total) { + + String debug = ""; + + } + + i++; + } + + if (tmpResults == null) { + tmpResults = josTypeResultArray; + } else { + int firstLength = tmpResults.length; + int secondLength = josTypeResultArray.length; + Object[][] tmp = new Object[firstLength + secondLength][3]; + + System.arraycopy(tmpResults, 0, tmp, 0, firstLength); + System.arraycopy(josTypeResultArray, 0, tmp, firstLength, secondLength); + + tmpResults = tmp; + + // tmpResults = ArrayUtils.addAll(tmpResults, josTypeResultArray); + } + } + + private static void printArray() { + for (int i = 0; i < tmpResults.length; i++) { + for (int j = 0; j < tmpResults[i].length; j++) { + System.out.print(tmpResults[i][j] + "\t"); + } + System.out.println(); + } + } +} diff --git a/src/main/java/alg/ngram/ForkJoin.java b/src/main/java/alg/ngram/ForkJoin.java new file mode 100644 index 0000000..e082814 --- /dev/null +++ b/src/main/java/alg/ngram/ForkJoin.java @@ -0,0 +1,62 @@ +package alg.ngram; + +import java.util.List; +import java.util.concurrent.RecursiveAction; + +import data.Sentence; +import data.StatisticsNew; + +public class ForkJoin extends RecursiveAction { + private static final long serialVersionUID = 5074814035083362355L; + + private static final int ACCEPTABLE_SIZE = 1000; + private List corpus; + private StatisticsNew stats; + private int start; + private int end; + + + /** + * Constructor for subproblems. + */ + private ForkJoin(List corpus, int start, int end, StatisticsNew stats) { + this.corpus = corpus; + this.start = start; + this.end = end; + this.stats = stats; + } + + /** + * Default constructor for the initial problem + */ + public ForkJoin(List corpus, StatisticsNew stats) { + this.corpus = corpus; + this.start = 0; + this.end = corpus.size(); + this.stats = stats; + } + + private void computeDirectly() { + List subCorpus = corpus.subList(start, end); + Ngrams.calculateForAll(subCorpus, stats); + } + + @Override + protected void compute() { + int subCorpusSize = end - start; + + if (subCorpusSize < ACCEPTABLE_SIZE) { + computeDirectly(); + } else { + int mid = start + subCorpusSize / 2; + ForkJoin left = new ForkJoin(corpus, start, mid, stats); + ForkJoin right = new ForkJoin(corpus, mid, end, stats); + + // fork (push to queue)-> compute -> join + left.fork(); + right.fork(); + left.join(); + right.join(); + } + } +} diff --git a/src/main/java/alg/ngram/Ngrams.java b/src/main/java/alg/ngram/Ngrams.java new file mode 100644 index 0000000..4b0f930 --- /dev/null +++ b/src/main/java/alg/ngram/Ngrams.java @@ -0,0 +1,204 @@ +package alg.ngram; + + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import data.CalculateFor; +import data.Sentence; +import data.StatisticsNew; +import data.Word; +import gui.ValidationUtil; + +public class Ngrams { + public final static Logger logger = LogManager.getLogger(Ngrams.class); + + + public static void calculateForAll(List corpus, StatisticsNew stats) { + if (stats.getFilter().getNgramValue() == 0) { // letter ngram + generateNgramLetterCandidates(corpus, stats); + } else if (!ValidationUtil.isEmpty(stats.getFilter().getSkipValue()) && stats.getFilter().getSkipValue() > 0) { + generateSkipgramCandidates(corpus, stats); + } else { + generateNgramCandidates(corpus, stats); + } + } + + public static void generateNgramCandidates(List corpus, StatisticsNew stats) { + for (Sentence s : corpus) { + // skip sentences shorter than specified ngram length + if (s.getWords().size() < stats.getFilter().getNgramValue()) { + continue; + } + + for (int i = 0; i < s.getWords().size() - stats.getFilter().getNgramValue() + 1; i++) { + List ngramCandidate = s.getSublist(i, i + stats.getFilter().getNgramValue()); + + // if msd regex is set and this candidate doesn't pass it, skip this iteration + if (stats.getFilter().hasMsd() && !passesRegex(ngramCandidate, stats.getFilter().getMsd())) { + continue; + } + + stats.updateResults(wordToString(ngramCandidate, stats.getFilter().getCalculateFor())); + } + } + } + + /** + * Checks whether an ngram candidate passes specified regex filter. + */ + private static boolean passesRegex(List ngramCandidate, ArrayList regex) { + if (ngramCandidate.size() != regex.size()) { + logger.error("ngramCandidate.size() & msd.size() mismatch"); // should not occur anyway + return false; + } + + for (int i = 0; i < regex.size(); i++) { + if (!ngramCandidate.get(i).getMsd().matches(regex.get(i).pattern())) { + return false; + } + } + + return true; + } + + private static String wordToString(List ngramCandidate, CalculateFor calculateFor) { + ArrayList candidate = new ArrayList<>(ngramCandidate.size()); + + switch (calculateFor) { + case LEMMA: + candidate.addAll(ngramCandidate + .stream() + .map(Word::getLemma) + .collect(Collectors.toList())); + break; + case WORD: + candidate.addAll(ngramCandidate + .stream() + .map(Word::getWord) + .collect(Collectors.toList())); + break; + case MORPHOSYNTACTIC_SPECS: + case MORPHOSYNTACTIC_PROPERTY: + candidate.addAll(ngramCandidate + .stream() + .map(Word::getMsd) + .collect(Collectors.toList())); + break; + case WORD_TYPE: + candidate.addAll(ngramCandidate + .stream() + .map(w -> Character.toString(w.getMsd().charAt(0))) + .collect(Collectors.toList())); + break; + } + + return StringUtils.join(candidate, " "); + } + + /** + * Generates candidates and updates results + * + * @param corpus + * @param stats + */ + private static void generateNgramLetterCandidates(List corpus, StatisticsNew stats) { + for (Sentence s : corpus) { + for (Word w : s.getWords()) { + String word = w.getForCf(stats.getFilter().getCalculateFor(), stats.getFilter().isCvv()); + + // skip this iteration if: + // - word doesn't contain a proper version (missing lemma for example) + // - msd regex is given but this word's msd doesn't match it, skip this iteration + // - given substring length is larger than the word length + if (ValidationUtil.isEmpty(word) + || stats.getFilter().hasMsd() && !w.getMsd().matches(stats.getFilter().getMsd().get(0).pattern()) + || word.length() < stats.getFilter().getStringLength()) { + continue; + } + + for (int i = 0; i < word.length() - stats.getFilter().getStringLength() + 1; i++) { + // TODO: locila? + stats.updateResults(word.substring(i, i + stats.getFilter().getStringLength())); + } + } + } + } + + + /** + * Extracts skipgram candidates. + * + * @return List of candidates represented as a list + */ + public static void generateSkipgramCandidates(List corpus, StatisticsNew stats) { + ArrayList currentLoop; + int ngram = stats.getFilter().getNgramValue(); + int skip = stats.getFilter().getSkipValue(); + + for (Sentence s : corpus) { + List sentence = s.getWords(); + + for (int i = 0; i <= sentence.size() - ngram; i++) { // 1gram + for (int j = i + 1; j <= i + skip + 1; j++) { // 2gram + if (ngram == 2 && j < sentence.size()) { + currentLoop = new ArrayList<>(); + currentLoop.add(sentence.get(i)); + currentLoop.add(sentence.get(j)); + + validateAndCountSkipgramCandidate(currentLoop, stats); + } else { + for (int k = j + 1; k <= j + 1 + skip; k++) { // 3gram + if (ngram == 3 && k < sentence.size()) { + currentLoop = new ArrayList<>(); + currentLoop.add(sentence.get(i)); + currentLoop.add(sentence.get(j)); + currentLoop.add(sentence.get(k)); + + validateAndCountSkipgramCandidate(currentLoop, stats); + } else { + for (int l = k + 1; l <= k + 1 + skip; l++) { // 4gram + if (ngram == 4 && k < sentence.size()) { + currentLoop = new ArrayList<>(); + currentLoop.add(sentence.get(i)); + currentLoop.add(sentence.get(j)); + currentLoop.add(sentence.get(k)); + currentLoop.add(sentence.get(l)); + + validateAndCountSkipgramCandidate(currentLoop, stats); + } else { + for (int m = k + 1; m <= k + 1 + skip; m++) { // 5gram + if (ngram == 5 && k < sentence.size()) { + currentLoop = new ArrayList<>(); + currentLoop.add(sentence.get(i)); + currentLoop.add(sentence.get(j)); + currentLoop.add(sentence.get(k)); + currentLoop.add(sentence.get(l)); + currentLoop.add(sentence.get(m)); + + validateAndCountSkipgramCandidate(currentLoop, stats); + } + } + } + } + } + } + } + } + } + } + } + + private static void validateAndCountSkipgramCandidate(ArrayList skipgramCandidate, StatisticsNew stats) { + // count if no regex is set or if it is & candidate passes it + if (!stats.getFilter().hasMsd() || passesRegex(skipgramCandidate, stats.getFilter().getMsd())) { + stats.updateResults(wordToString(skipgramCandidate, stats.getFilter().getCalculateFor())); + } + } +} diff --git a/src/main/java/alg/word/ForkJoin.java b/src/main/java/alg/word/ForkJoin.java new file mode 100644 index 0000000..cb4965a --- /dev/null +++ b/src/main/java/alg/word/ForkJoin.java @@ -0,0 +1,62 @@ +package alg.word; + +import java.util.List; +import java.util.concurrent.RecursiveAction; + +import data.Sentence; +import data.StatisticsNew; + +public class ForkJoin extends RecursiveAction { + private static final long serialVersionUID = 7711587510996456040L; + + private static final int ACCEPTABLE_SIZE = 1000; + private List corpus; + private StatisticsNew stats; + private int start; + private int end; + + + /** + * Constructor for subproblems. + */ + private ForkJoin(List corpus, int start, int end, StatisticsNew stats) { + this.corpus = corpus; + this.start = start; + this.end = end; + this.stats = stats; + } + + /** + * Default constructor for the initial problem + */ + public ForkJoin(List corpus, StatisticsNew stats) { + this.corpus = corpus; + this.start = 0; + this.end = corpus.size(); + this.stats = stats; + } + + private void computeDirectly() { + List subCorpus = corpus.subList(start, end); + WordLevel.calculateForAll(subCorpus, stats); + } + + @Override + protected void compute() { + int subCorpusSize = end - start; + + if (subCorpusSize < ACCEPTABLE_SIZE) { + computeDirectly(); + } else { + int mid = start + subCorpusSize / 2; + ForkJoin left = new ForkJoin(corpus, start, mid, stats); + ForkJoin right = new ForkJoin(corpus, mid, end, stats); + + // fork (push to queue)-> compute -> join + left.fork(); + right.fork(); + left.join(); + right.join(); + } + } +} diff --git a/src/main/java/alg/word/WordCount.java b/src/main/java/alg/word/WordCount.java new file mode 100644 index 0000000..9eac4b0 --- /dev/null +++ b/src/main/java/alg/word/WordCount.java @@ -0,0 +1,167 @@ +package alg.word; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import alg.Common; +import data.CalculateFor; +import data.Sentence; +import data.Statistics; +import data.Word; + +class WordCount { + private static void calculateNoFilter(List corpus, Statistics stats) { + for (Sentence s : corpus) { + List sentence = new ArrayList<>(s.getWords().size()); + + if (stats.getCf() == CalculateFor.LEMMA) { + sentence.addAll(s.getWords() + .stream() + .map(Word::getLemma) + .collect(Collectors.toList())); + } else if (stats.getCf() == CalculateFor.WORD) { + sentence.addAll(s.getWords() + .stream() + .map(Word::getWord) + .collect(Collectors.toList())); + } + + for (String word : sentence) { + Common.updateMap(stats.result, word); + } + } + } + + private static void calculateVCC(List corpus, Statistics stats) { + for (Sentence s : corpus) { + List sentence = new ArrayList<>(s.getWords().size()); + + if (stats.getCf() == CalculateFor.LEMMA) { + sentence.addAll(s.getWords() + .stream() + .map(Word::getCVVLemma) + .collect(Collectors.toList())); + } else if (stats.getCf() == CalculateFor.WORD) { + sentence.addAll(s.getWords() + .stream() + .map(Word::getCVVWord) + .collect(Collectors.toList())); + } + + for (String word : sentence) { + if (word.length() > stats.getSubstringLength()) { + for (int i = 0; i <= word.length() - stats.getSubstringLength(); i++) { + String substring = word.substring(i, i + stats.getSubstringLength()); + Common.updateMap(stats.result, substring); + } + } + } + } + } + + private static void calculateForJosType(List corpus, Statistics stats) { + for (Sentence s : corpus) { + List sentence = new ArrayList<>(s.getWords().size()); + List filteredWords = new ArrayList<>(); + + for (Word word : s.getWords()) { + if (word.getMsd() != null && word.getMsd().charAt(0) == stats.getDistributionJosWordType()) { + filteredWords.add(word); + } + } + + if (stats.getCf() == CalculateFor.LEMMA) { + sentence.addAll(filteredWords + .stream() + .map(Word::getLemma) + .collect(Collectors.toList())); + } else if (stats.getCf() == CalculateFor.WORD) { + sentence.addAll(filteredWords + .stream() + .map(Word::getWord) + .collect(Collectors.toList())); + } + + for (String word : sentence) { + Common.updateMap(stats.result, word); + } + } + } + + private static void calculateForTaxonomyAndJosType(List corpus, Statistics stats) { + for (Sentence s : corpus) { + if (s.getTaxonomy().equalsIgnoreCase(stats.getDistributionTaxonomy())) { + List sentence = new ArrayList<>(s.getWords().size()); + List filteredWords = new ArrayList<>(); + + for (Word word : s.getWords()) { + if (word.getMsd().charAt(0) == stats.getDistributionJosWordType()) { + filteredWords.add(word); + } + } + + if (stats.getCf() == CalculateFor.LEMMA) { + sentence.addAll(filteredWords + .stream() + .map(Word::getLemma) + .collect(Collectors.toList())); + } else if (stats.getCf() == CalculateFor.WORD) { + sentence.addAll(filteredWords + .stream() + .map(Word::getWord) + .collect(Collectors.toList())); + } + + for (String word : sentence) { + Common.updateMap(stats.result, word); + } + } + } + } + + private static void calculateForTaxonomy(List corpus, Statistics stats) { + for (Sentence s : corpus) { + if (s.getTaxonomy().equalsIgnoreCase(stats.getDistributionTaxonomy())) { + List sentence = new ArrayList<>(s.getWords().size()); + + if (stats.getCf() == CalculateFor.LEMMA) { + sentence.addAll(s.getWords() + .stream() + .map(Word::getLemma) + .collect(Collectors.toList())); + } else if (stats.getCf() == CalculateFor.WORD) { + sentence.addAll(s.getWords() + .stream() + .map(Word::getWord) + .collect(Collectors.toList())); + } + + for (String word : sentence) { + Common.updateMap(stats.result, word); + } + } + } + } + + static void calculateForAll(List corpus, Statistics stats) { + boolean taxonomyIsSet = stats.isTaxonomySet(); + boolean JosTypeIsSet = stats.isJOSTypeSet(); + + // branching because even though the only difference is an if or two && + // O(if) = 1, the amount of ifs adds up and this saves some time + if (taxonomyIsSet && JosTypeIsSet) { + calculateForTaxonomyAndJosType(corpus, stats); + } else if (taxonomyIsSet && !JosTypeIsSet) { + calculateForTaxonomy(corpus, stats); + } else if (!taxonomyIsSet && JosTypeIsSet) { + calculateForJosType(corpus, stats); + } else { + if (stats.isVcc()) { + calculateVCC(corpus, stats); + } else { + calculateNoFilter(corpus, stats); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/alg/word/WordLevel.java b/src/main/java/alg/word/WordLevel.java new file mode 100644 index 0000000..5809c71 --- /dev/null +++ b/src/main/java/alg/word/WordLevel.java @@ -0,0 +1,112 @@ +package alg.word; + +import static data.Enums.WordLevelDefaultValues.*; + +import java.util.HashSet; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import data.Enums.WordLevelDefaultValues; +import data.Enums.WordLevelType; +import data.Sentence; +import data.StatisticsNew; +import data.Word; + +@SuppressWarnings("Duplicates") +public class WordLevel { + private static HashSet suffixes; + private static int minSuffixLength; + private static int maxSuffixLength; + + private static HashSet prefixes; + private static int minPrefixLength; + private static int maxPrefixLength; + + static { + suffixes = WordLevelDefaultValues.getSuffixes(); + calculateSuffixesLengths(); + + prefixes = WordLevelDefaultValues.getPrefixes(); + calculatePrefixesLengths(); + } + + public static void calculateForAll(List corpus, StatisticsNew stats) { + for (Sentence s : corpus) { + for (Word word : s.getWords()) { + calculateForSuffixes(word.getWord(), stats); + calculateForPrefixes(word.getWord(), stats); + } + } + } + + private static void calculateForPrefixes(String word, StatisticsNew stats) { + for (int tmpPrefixLength = maxPrefixLength; tmpPrefixLength >= minPrefixLength; tmpPrefixLength++) { + if (word.length() - tmpPrefixLength < MIN_N_OF_CHARACTERS_LEFT_PREFIX) { + return; + } + + String extractedPrefix = StringUtils.left(word, tmpPrefixLength); + + if (prefixes.contains(extractedPrefix)) { + // save suffix and full word + stats.updateResultsNested(WordLevelType.PREFIX, extractedPrefix, word); + return; + } + } + } + + public static void calculateForSuffixes(String word, StatisticsNew stats) { + for (int tmpSuffixLength = maxSuffixLength; tmpSuffixLength >= minSuffixLength; tmpSuffixLength++) { + // preveri, da je beseda - cuttan suffix daljši od prednastavljene vrednosti + // ker gremo od najdaljše opcije k najkrajši, se ob dosegu tega pogoja lahko zaključi računanje za trenutno besedo + if (word.length() - tmpSuffixLength < MIN_N_OF_CHARACTERS_LEFT_SUFFIX) { + return; + } + + String extractedSuffix = StringUtils.right(word, tmpSuffixLength); + + if (suffixes.contains(extractedSuffix)) { + // save suffix and full word + stats.updateResultsNested(WordLevelType.SUFFIX, extractedSuffix, word); + return; + } + } + } + + // finds the shortest and longest suffix for quicker calculations + public static void calculateSuffixesLengths() { + minSuffixLength = -1; + maxSuffixLength = -1; + + for (String suffix : suffixes) { + if (suffix.length() > maxSuffixLength) { + maxSuffixLength = suffix.length(); + + if (minSuffixLength < 0) { + minSuffixLength = maxSuffixLength; + } + } else if (suffix.length() < minSuffixLength) { + minSuffixLength = suffix.length(); + } + } + } + + // finds the shortest and longest suffix for quicker calculations + public static void calculatePrefixesLengths() { + minPrefixLength = -1; + maxPrefixLength = -1; + + for (String prefix : prefixes) { + if (prefix.length() > maxPrefixLength) { + maxPrefixLength = prefix.length(); + + if (minPrefixLength < 0) { + minPrefixLength = maxPrefixLength; + } + } else if (prefix.length() < minPrefixLength) { + minPrefixLength = prefix.length(); + } + } + } +} diff --git a/src/main/java/data/AnalysisLevel.java b/src/main/java/data/AnalysisLevel.java new file mode 100644 index 0000000..c3a4ee4 --- /dev/null +++ b/src/main/java/data/AnalysisLevel.java @@ -0,0 +1,17 @@ +package data; + +public enum AnalysisLevel { + STRING_LEVEL("Besedni nizi"), + WORD_LEVEL("Nivo besed in delov besed"), + WORD_FORMATION("Besedotvorni procesi"); + + private final String name; + + AnalysisLevel(String name) { + this.name = name; + } + + public String toString() { + return this.name; + } +} \ No newline at end of file diff --git a/src/main/java/data/CalculateFor.java b/src/main/java/data/CalculateFor.java new file mode 100644 index 0000000..5146957 --- /dev/null +++ b/src/main/java/data/CalculateFor.java @@ -0,0 +1,43 @@ +package data; + +public enum CalculateFor { + WORD("različnica"), + LEMMA("lema"), + MORPHOSYNTACTIC_SPECS("oblikoskladenjska oznaka"), + MORPHOSYNTACTIC_PROPERTY("oblikoskladenjska lastnost"), + WORD_TYPE("besedna vrsta"), + DIST_WORDS("različnica"), + DIST_LEMMAS("lema"); + + + private final String name; + + CalculateFor(String name) { + this.name = name; + } + + public String toString() { + return this.name; + } + + public static CalculateFor factory(String cf) { + if (cf != null) { + if (WORD.toString().equals(cf)) { + return WORD; + } + if (LEMMA.toString().equals(cf)) { + return LEMMA; + } + if (MORPHOSYNTACTIC_SPECS.toString().equals(cf)) { + return MORPHOSYNTACTIC_SPECS; + } + if (MORPHOSYNTACTIC_PROPERTY.toString().equals(cf)) { + return MORPHOSYNTACTIC_PROPERTY; + } + if (WORD_TYPE.toString().equals(cf)) { + return WORD_TYPE; + } + } + return null; + } +} diff --git a/src/main/java/data/Corpus.java b/src/main/java/data/Corpus.java new file mode 100644 index 0000000..6bc35bd --- /dev/null +++ b/src/main/java/data/Corpus.java @@ -0,0 +1,163 @@ +package data; + +import static gui.Messages.*; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; + +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import data.Enums.solar.SolarFilters; +import gui.ValidationUtil; +import javafx.collections.ObservableList; + +public class Corpus { + public final static Logger logger = LogManager.getLogger(Corpus.class); + + private CorpusType corpusType; + private File chosenResultsLocation; + private File chosenCorpusLocation; + private Collection detectedCorpusFiles; + boolean headerRead; + private ObservableList taxonomy; // if gigafida or gos + private HashMap> solarFilters; // if solar + private HashMap> solarFiltersForXML; // if solar - used while parsing xml + private boolean gosOrthMode; + boolean hasMsdData; + private ArrayList validationErrors; + + public Corpus() { + validationErrors = new ArrayList<>(); + } + + public CorpusType getCorpusType() { + return corpusType; + } + + public void setCorpusType(CorpusType corpusType) { + this.corpusType = corpusType; + logger.info("Corpus.set: ", corpusType); + } + + public File getChosenResultsLocation() { + return chosenResultsLocation; + } + + public void setChosenResultsLocation(File chosenResultsLocation) { + this.chosenResultsLocation = chosenResultsLocation; + logger.info("Corpus.set: ", chosenResultsLocation); + } + + public File getChosenCorpusLocation() { + return chosenCorpusLocation; + } + + public void setChosenCorpusLocation(File chosenCorpusLocation) { + this.chosenCorpusLocation = chosenCorpusLocation; + logger.info("Corpus.set: ", chosenCorpusLocation); + } + + public Collection getDetectedCorpusFiles() { + return detectedCorpusFiles; + } + + public void setDetectedCorpusFiles(Collection detectedCorpusFiles) { + this.detectedCorpusFiles = detectedCorpusFiles; + logger.info("Corpus.set: ", detectedCorpusFiles); + } + + public boolean isHeaderRead() { + return headerRead; + } + + public void setHeaderRead(boolean headerRead) { + this.headerRead = headerRead; + } + + public ObservableList getTaxonomy() { + return taxonomy; + } + + public void setTaxonomy(ObservableList taxonomy) { + this.taxonomy = taxonomy; + logger.info("Corpus.set: ", taxonomy); + } + + public HashMap> getSolarFilters() { + return solarFilters; + } + + public void setSolarFilters(HashMap> solarFilters) { + this.solarFilters = solarFilters; + logger.info("Corpus.set: ", solarFilters); + } + + public HashMap> getSolarFiltersForXML() { + return solarFiltersForXML; + } + + public void setSolarFiltersForXML(HashMap> solarFiltersForXML) { + this.solarFiltersForXML = solarFiltersForXML; + logger.info("Corpus.set: ", solarFiltersForXML); + } + + public boolean isGosOrthMode() { + return gosOrthMode; + } + + public void setGosOrthMode(boolean gosOrthMode) { + this.gosOrthMode = gosOrthMode; + logger.info("Corpus.set: ", gosOrthMode); + } + + public ArrayList getValidationErrors() { + return validationErrors; + } + + public String getValidationErrorsToString() { + return StringUtils.join(validationErrors, "\n - "); + } + + public void setValidationErrors(ArrayList validationErrors) { + this.validationErrors = validationErrors; + } + + public boolean validate() { + if (corpusType == null) { + validationErrors.add(LABEL_RESULTS_CORPUS_TYPE_NOT_SET); + } + + if (chosenCorpusLocation == null) { + validationErrors.add(LABEL_CORPUS_LOCATION_NOT_SET); + } + + if (chosenResultsLocation == null) { + validationErrors.add(LABEL_RESULTS_LOCATION_NOT_SET); + } + + if (!headerRead && corpusType != null) { + // if user didn't opt into reading the headers, set default taxonomy or solar filters + if (Tax.getCorpusTypesWithTaxonomy().contains(corpusType)) { + taxonomy = Tax.getTaxonomyForComboBox(corpusType); + } else if (corpusType == CorpusType.SOLAR && solarFilters == null) { + setSolarFilters(SolarFilters.getFiltersForComboBoxes()); + } + } + + if (headerRead && ValidationUtil.isEmpty(taxonomy)) { + // mustn't happen, intercept at gui level + } + + if (!ValidationUtil.isEmpty(validationErrors)) { + logger.error("Corpus validation error: ", StringUtils.join(validationErrors, "\n - ")); + return false; + } else { + return true; + } + } +} diff --git a/src/main/java/data/CorpusType.java b/src/main/java/data/CorpusType.java new file mode 100644 index 0000000..2c70385 --- /dev/null +++ b/src/main/java/data/CorpusType.java @@ -0,0 +1,25 @@ +package data; + +public enum CorpusType { + GIGAFIDA("Gigafida", "gigafida"), + CCKRES("ccKres ", "cckres"), + SOLAR("Šolar", "šolar"), + GOS("GOS", "gos"); + + + private final String name; + private final String nameLowerCase; + + CorpusType(String name, String nameLowerCase) { + this.name = name; + this.nameLowerCase = nameLowerCase; + } + + public String toString() { + return this.name; + } + + public String getNameLowerCase() { + return nameLowerCase; + } +} diff --git a/src/main/java/data/Enums/InflectedJosTypes.java b/src/main/java/data/Enums/InflectedJosTypes.java new file mode 100644 index 0000000..a5acbcf --- /dev/null +++ b/src/main/java/data/Enums/InflectedJosTypes.java @@ -0,0 +1,12 @@ +package data.Enums; + +import java.util.Arrays; +import java.util.HashSet; + +public class InflectedJosTypes { + public static final HashSet inflectedJosTypes = new HashSet<>(); + + static { + inflectedJosTypes.addAll(Arrays.asList('S', 'G', 'P')); + } +} diff --git a/src/main/java/data/Enums/Msd.java b/src/main/java/data/Enums/Msd.java new file mode 100644 index 0000000..950749f --- /dev/null +++ b/src/main/java/data/Enums/Msd.java @@ -0,0 +1,68 @@ +package data.Enums; + +import java.util.HashMap; + +public enum Msd { + NOUN("samostalnik", 'S', "Noun", 'N', 5), + VERB("glagol", 'G', "Verb", 'V', 7), + ADJECTIVE("pridevnik", 'P', "Adjective", 'A', 6), + ADVERB("prislov", 'R', "Adverb", 'R', 2), + PRONOUN("zaimek", 'Z', "Pronoun", 'P', 8), + NUMERAL("števnik", 'K', "Numeral", 'M', 6), + PREPOSITION("predlog", 'D', "Preposition", 'S', 1), + CONJUNCTION("veznik", 'V', "Conjunction", 'C', 1), + PARTICLE("členek", 'L', "Particle", 'Q', 0), + INTERJECTION("medmet", 'M', "Interjection", 'I', 0), + ABBREVIATION("okrajšava", 'O', "Abbreviation", 'Y', 0), + RESIDUAL("neuvrščeno", 'N', "Residual", 'X', 1); + + private final String siName; + private final Character siCode; + private final String enName; + private final Character enCode; + private final Integer nOfAttributes; + + private static HashMap siCodeNOfAttributes; + + static { + siCodeNOfAttributes = new HashMap<>(); + for (Msd msd : Msd.values()) { + siCodeNOfAttributes.put(msd.getSiCode(), msd.nOfAttributes); + } + } + + Msd(String siName, Character siCode, String enName, Character enCode, int nOfAttributes) { + this.siName = siName; + this.siCode = siCode; + this.enName = enName; + this.enCode = enCode; + this.nOfAttributes = nOfAttributes; + } + + public String getSiName() { + return siName; + } + + public Character getSiCode() { + return siCode; + } + + public String getEnName() { + return enName; + } + + public Character getEnCode() { + return enCode; + } + + /** + * Returns the number of attributes for the given type. + * + * @param msd + * + * @return + */ + public static int getMsdLengthForType(String msd) { + return siCodeNOfAttributes.get(msd.charAt(0)) + 1; + } +} diff --git a/src/main/java/data/Enums/WordLevelDefaultValues.java b/src/main/java/data/Enums/WordLevelDefaultValues.java new file mode 100644 index 0000000..91d1c0f --- /dev/null +++ b/src/main/java/data/Enums/WordLevelDefaultValues.java @@ -0,0 +1,55 @@ +package data.Enums; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class WordLevelDefaultValues { + public final static Logger logger = LogManager.getLogger(WordLevelDefaultValues.class); + + private static HashSet suffixes; + private static final String SUFFIXES_FILE = "/Lists/suffixes.txt"; + public static final int MIN_N_OF_CHARACTERS_LEFT_SUFFIX = 2; + + private static HashSet prefixes; + private static final String PREFIXES_FILE = "/Lists/prefixes.txt"; + public static final int MIN_N_OF_CHARACTERS_LEFT_PREFIX = 2; + + static { + suffixes = new HashSet<>(); + suffixes = readFromFile(SUFFIXES_FILE); + prefixes = new HashSet<>(); + prefixes = readFromFile(PREFIXES_FILE); + } + + private static HashSet readFromFile(String fileName) { + Set dictionary = new HashSet<>(); + + try (InputStream is = WordLevelDefaultValues.class.getClass().getResourceAsStream(fileName)) { + if (is != null) { + // TODO: warn if !exists + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + dictionary = reader.lines().collect(Collectors.toSet()); + } + } catch (IOException e) { + logger.error("Problem reading init dictionary", e); + } + + return (HashSet) dictionary; + } + + public static HashSet getSuffixes() { + return suffixes; + } + + public static HashSet getPrefixes() { + return prefixes; + } +} diff --git a/src/main/java/data/Enums/WordLevelType.java b/src/main/java/data/Enums/WordLevelType.java new file mode 100644 index 0000000..564105d --- /dev/null +++ b/src/main/java/data/Enums/WordLevelType.java @@ -0,0 +1,16 @@ +package data.Enums; + +public enum WordLevelType { + SUFFIX("pripona"), + PREFIX("predpona"); + + private final String name; + + WordLevelType(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/data/Enums/solar/SolarFilters.java b/src/main/java/data/Enums/solar/SolarFilters.java new file mode 100644 index 0000000..efd4aea --- /dev/null +++ b/src/main/java/data/Enums/solar/SolarFilters.java @@ -0,0 +1,57 @@ +package data.Enums.solar; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +public class SolarFilters { + private static HashMap> SOLAR_FILTERS; + public static final String SOLA = "sola"; + public static final String PREDMET = "predmet"; + public static final String RAZRED = "razred"; + public static final String REGIJA = "regija"; + public static final String TIP = "tip"; + public static final String LETO = "leto"; + + static { + SOLAR_FILTERS = new HashMap<>(); + + SOLAR_FILTERS.put(REGIJA, FXCollections.observableArrayList("Celje", "Gorica", "Koper", "Kranj", "Krško", "Ljubljana", "Maribor", "Murska Sobota", "Novo mesto", "Postojna", "Slovenj Gradec")); + SOLAR_FILTERS.put(PREDMET, FXCollections.observableArrayList("državljanska vzgoja in etika", "ekonomija", "filozofija", "geografija", "kemija", "podjetništvo", "psihologija", "slovenščina", "sociologija", "umetnostna vzgoja", "zgodovina")); + SOLAR_FILTERS.put(RAZRED, FXCollections.observableArrayList("6. razred", "7. razred", "8. razred", "9. razred", "1. letnik", "2. letnik", "3. letnik", "4. letnik", "5. letnik", "maturitetni tečaj")); + SOLAR_FILTERS.put(LETO, FXCollections.observableArrayList("2007", "2008", "2009", "2009/2010", "2010")); + SOLAR_FILTERS.put(SOLA, FXCollections.observableArrayList("gimnazija", "osnovna šola", "poklicna šola", "strokovna šola")); + SOLAR_FILTERS.put(TIP, FXCollections.observableArrayList("esej/spis", "pisni izdelek (učna ura)", "test (daljše besedilo)", "test (odgovori na vprašanja)")); + } + + public static final ObservableList N_GRAM_COMPUTE_FOR_FULL = FXCollections.observableArrayList("različnica", "lema", "oblikoskladenjska oznaka", "oblikoskladenjska lastnost", "besedna vrsta"); + public static final ObservableList N_GRAM_COMPUTE_FOR_LIMITED = FXCollections.observableArrayList("različnica", "lema"); + + /** + * Returns filters with all possible values + */ + public static HashMap> getFiltersForComboBoxes() { + return SOLAR_FILTERS; + } + + /** + * Returns filters with all possible values + */ + public static HashMap> getFiltersForComboBoxes(HashMap> foundFilters) { + HashMap> filtersForComboBoxes = new HashMap<>(); + + for (Map.Entry> e : SOLAR_FILTERS.entrySet()) { + if (!foundFilters.containsKey(e.getKey())) { + // if, by some reason a specific filter wasn't in the corpus, return a blank list for that filter + filtersForComboBoxes.put(e.getKey(), FXCollections.observableArrayList()); + } else { + filtersForComboBoxes.put(e.getKey(), FXCollections.observableArrayList(foundFilters.get(e.getKey())).sorted()); + } + } + + return filtersForComboBoxes; + } +} diff --git a/src/main/java/data/Filter.java b/src/main/java/data/Filter.java new file mode 100644 index 0000000..733cb67 --- /dev/null +++ b/src/main/java/data/Filter.java @@ -0,0 +1,144 @@ +package data; + +import static data.Filter.filterName.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.regex.Pattern; + +import gui.ValidationUtil; + +@SuppressWarnings("unchecked") +public class Filter { + private HashMap filter; + + public enum filterName { + ANALYSIS_LEVEL, + CALCULATE_FOR, + NGRAM_VALUE, + SKIP_VALUE, + IS_CVV, + STRING_LENGTH, + TAXONOMY, + MSD, + HAS_MSD, + SOLAR_FILTERS + } + + public Filter() { + filter = new HashMap<>(); + } + + public Filter(AnalysisLevel al, CalculateFor cf) { + filter = new HashMap<>(); + + filter.put(ANALYSIS_LEVEL, al); + filter.put(CALCULATE_FOR, cf); + } + + public void setAl(AnalysisLevel al) { + filter.put(ANALYSIS_LEVEL, al); + } + + public AnalysisLevel getAl() { + return (AnalysisLevel) filter.get(ANALYSIS_LEVEL); + } + + public void setCalculateFor(CalculateFor cf) { + filter.put(CALCULATE_FOR, cf); + } + + public CalculateFor getCalculateFor() { + return (CalculateFor) filter.get(CALCULATE_FOR); + } + + public void setNgramValue(Integer ngramValue) { + filter.put(NGRAM_VALUE, ngramValue); + } + + public Integer getNgramValue() { + return (Integer) filter.get(NGRAM_VALUE); + } + + public void setSkipValue(Integer skipValue) { + filter.put(SKIP_VALUE, skipValue); + } + + public Integer getSkipValue() { + return (Integer) filter.get(SKIP_VALUE); + } + + public void setIsCvv(boolean isCvv) { + filter.put(IS_CVV, isCvv); + } + + public boolean isCvv() { + return filter.containsKey(IS_CVV) && (boolean) filter.get(IS_CVV); + } + + public void setStringLength(int stringLength) { + filter.put(STRING_LENGTH, stringLength); + } + + public Integer getStringLength() { + return (Integer) filter.get(STRING_LENGTH); + } + + public void setTaxonomy(ArrayList taxonomy) { + filter.put(TAXONOMY, taxonomy); + } + + public ArrayList getTaxonomy() { + if (filter.containsKey(TAXONOMY) && filter.get(TAXONOMY) != null) { + return (ArrayList) filter.get(TAXONOMY); + } else { + return new ArrayList<>(); + } + } + + public void setMsd(ArrayList msd) { + filter.put(MSD, msd); + if (!ValidationUtil.isEmpty(msd)) { + setHasMsd(true); + } else { + setHasMsd(false); + } + } + + public ArrayList getMsd() { + return (ArrayList) filter.get(MSD); + } + + public void setHasMsd(boolean hasMsd) { + filter.put(HAS_MSD, hasMsd); + } + + public boolean hasMsd() { + return filter.containsKey(HAS_MSD) && (boolean) filter.get(HAS_MSD); + } + + public String toString() { + String newLine = "\n\t- "; + StringBuilder sb = new StringBuilder(); + + sb.append(newLine).append("Filter:"); + for (Map.Entry entry : filter.entrySet()) { + sb.append(newLine) + .append(entry.getKey().toString()) + .append(": ") + .append(entry.getValue() != null ? entry.getValue().toString() : "null"); + } + + return sb.toString(); + } + + public void setSolarFilters(HashMap> filters) { + filter.put(SOLAR_FILTERS, filters); + } + + public HashMap> getSolarFilters() { + return (HashMap>) filter.get(SOLAR_FILTERS); + } +} diff --git a/src/main/java/data/GigafidaJosWordType.java b/src/main/java/data/GigafidaJosWordType.java new file mode 100644 index 0000000..9e32953 --- /dev/null +++ b/src/main/java/data/GigafidaJosWordType.java @@ -0,0 +1,71 @@ +package data; + +public enum GigafidaJosWordType { + SAMOSTALNIK("samostalnik", 'S'), + GLAGOL("glagol", 'G'), + PRIDEVNIK("pridevnik", 'P'), + PRISLOV("prislov", 'R'), + ZAIMEK("zaimek", 'Z'), + STEVNIK("stevnik", 'K'), + PREDLOG("predlog", 'D'), + VEZNIK("veznik", 'V'), + CLENEK("clenek", 'L'), + MEDMET("medmet", 'M'), + OKRAJSAVA("okrajsava", 'O'); + + + private final String name; + private final char wordType; + + GigafidaJosWordType(String name, char wordType) { + this.name = name; + this.wordType = wordType; + } + + public String toString() { + return this.name; + } + + public char getWordType() { + return wordType; + } + + public static GigafidaJosWordType factory(String wType) { + if (wType != null) { + if (SAMOSTALNIK.toString().equals(wType)) { + return SAMOSTALNIK; + } + if (GLAGOL.toString().equals(wType)) { + return GLAGOL; + } + if (PRIDEVNIK.toString().equals(wType)) { + return PRIDEVNIK; + } + if (PRISLOV.toString().equals(wType)) { + return PRISLOV; + } + if (ZAIMEK.toString().equals(wType)) { + return ZAIMEK; + } + if (STEVNIK.toString().equals(wType)) { + return STEVNIK; + } + if (PREDLOG.toString().equals(wType)) { + return PREDLOG; + } + if (VEZNIK.toString().equals(wType)) { + return VEZNIK; + } + if (CLENEK.toString().equals(wType)) { + return CLENEK; + } + if (MEDMET.toString().equals(wType)) { + return MEDMET; + } + if (OKRAJSAVA.toString().equals(wType)) { + return OKRAJSAVA; + } + } + return null; + } +} diff --git a/src/main/java/data/GigafidaTaxonomy.java b/src/main/java/data/GigafidaTaxonomy.java new file mode 100644 index 0000000..cafde32 --- /dev/null +++ b/src/main/java/data/GigafidaTaxonomy.java @@ -0,0 +1,76 @@ +package data; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.Collectors; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +public enum GigafidaTaxonomy { + TISK("tisk", "T"), + KNJIZNO("knjižno", "T.K"), + LEPOSLOVNO("leposlovno", "T.K.L"), + STROKOVNO("strokovno", "T.K.S"), + PERIODICNO("periodično", "T.P"), + CASOPIS("časopis", "T.P.C"), + REVIJA("revija", "T.P.R"), + INTERNET("internet", "I"); + + private final String name; + private final String taxonomy; + + private static final ObservableList FOR_COMBO_BOX; + + static { + ArrayList values = Arrays.stream(GigafidaTaxonomy.values()).map(x -> x.name).collect(Collectors.toCollection(ArrayList::new)); + FOR_COMBO_BOX = FXCollections.observableArrayList(values); + } + + GigafidaTaxonomy(String name, String taxonomy) { + this.name = name; + this.taxonomy = taxonomy; + } + + public String toString() { + return this.name; + } + + public String getTaxonomnyString() { + return this.taxonomy; + } + + public static GigafidaTaxonomy factory(String tax) { + if (tax != null) { + if (TISK.toString().equals(tax)) { + return TISK; + } + if (KNJIZNO.toString().equals(tax)) { + return KNJIZNO; + } + if (LEPOSLOVNO.toString().equals(tax)) { + return LEPOSLOVNO; + } + if (STROKOVNO.toString().equals(tax)) { + return STROKOVNO; + } + if (PERIODICNO.toString().equals(tax)) { + return PERIODICNO; + } + if (CASOPIS.toString().equals(tax)) { + return CASOPIS; + } + if (REVIJA.toString().equals(tax)) { + return REVIJA; + } + if (INTERNET.toString().equals(tax)) { + return INTERNET; + } + } + return null; + } + + public static ObservableList getForComboBox() { + return FOR_COMBO_BOX; + } +} diff --git a/src/main/java/data/GosTaxonomy.java b/src/main/java/data/GosTaxonomy.java new file mode 100644 index 0000000..454abad --- /dev/null +++ b/src/main/java/data/GosTaxonomy.java @@ -0,0 +1,85 @@ +package data; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.Collectors; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +public enum GosTaxonomy { + JAVNI("javni", "gos.T.J"), + INFORMATIVNO_IZOBRAZEVALNI("informativno-izobraževalni", "gos.T.J.I"), + RAZVEDRILNI("razvedrilni", "gos.T.J.R"), + NEJAVNI("nejavni", "gos.T.N"), + NEZASEBNI("nezasebni", "gos.T.N.N"), + ZASEBNI("zasebni", "gos.T.N.Z"), + OSEBNI_STIK("osebni stik", "gos.K.O"), + TELEFON("telefon", "gos.K.P"), + RADIO("radio", "gos.K.R"), + TELEVIZIJA("televizija", "gos.K.T"); + + + private final String name; + private final String taxonomy; + + private static final ObservableList FOR_COMBO_BOX; + + static { + ArrayList values = Arrays.stream(GosTaxonomy.values()).map(x -> x.name).collect(Collectors.toCollection(ArrayList::new)); + FOR_COMBO_BOX = FXCollections.observableArrayList(values); + } + + GosTaxonomy(String name, String taxonomy) { + this.name = name; + this.taxonomy = taxonomy; + } + + public String toString() { + return this.name; + } + + public String getTaxonomnyString() { + return this.taxonomy; + } + + public static GosTaxonomy factory(String tax) { + if (tax != null) { + if (JAVNI.toString().equals(tax)) { + return JAVNI; + } + if (INFORMATIVNO_IZOBRAZEVALNI.toString().equals(tax)) { + return INFORMATIVNO_IZOBRAZEVALNI; + } + if (RAZVEDRILNI.toString().equals(tax)) { + return RAZVEDRILNI; + } + if (NEJAVNI.toString().equals(tax)) { + return NEJAVNI; + } + if (NEZASEBNI.toString().equals(tax)) { + return NEZASEBNI; + } + if (ZASEBNI.toString().equals(tax)) { + return ZASEBNI; + } + if (OSEBNI_STIK.toString().equals(tax)) { + return OSEBNI_STIK; + } + if (TELEFON.toString().equals(tax)) { + return TELEFON; + } + if (RADIO.toString().equals(tax)) { + return RADIO; + } + if (TELEVIZIJA.toString().equals(tax)) { + return TELEVIZIJA; + } + } + return null; + } + + public static ObservableList getForComboBox() { + return FOR_COMBO_BOX; + } +} diff --git a/src/main/java/data/Sentence.java b/src/main/java/data/Sentence.java new file mode 100644 index 0000000..00a1a39 --- /dev/null +++ b/src/main/java/data/Sentence.java @@ -0,0 +1,56 @@ +package data; + +import java.util.List; +import java.util.Map; + +public class Sentence { + + + private List words; + private String taksonomija; + + // GOS + private String type; + private Map properties; + + public Sentence(List words, String taksonomija) { + this.words = words; + this.taksonomija = taksonomija; + } + + public Sentence(List words) { + this.words = words; + } + + public Sentence(List words, String taksonomija, Map properties) { + this.words = words; + this.taksonomija = taksonomija; + this.properties = properties; + } + + public Sentence(List words, String taksonomija, String type) { + this.words = words; + this.taksonomija = taksonomija; + this.type = type; + } + + public List getWords() { + return words; + } + + public String getTaxonomy() { + return taksonomija; + } + + public List getSublist(int indexFrom, int indexTo) { + return this.words.subList(indexFrom, indexTo); + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/src/main/java/data/Settings.java b/src/main/java/data/Settings.java new file mode 100644 index 0000000..b84e5d0 --- /dev/null +++ b/src/main/java/data/Settings.java @@ -0,0 +1,16 @@ +package data; + + +import java.io.File; +import java.util.Collection; + +public class Settings { + public static final int CORPUS_SENTENCE_LIMIT = 50000; + public static final boolean PRINT_LOG = false; + + public static final String FX_ACCENT_OK = "-fx-accent: forestgreen;"; + public static final String FX_ACCENT_NOK = "-fx-accent: red;"; + + public static Collection corpus; + public static File resultsFilePath; +} diff --git a/src/main/java/data/Statistics.java b/src/main/java/data/Statistics.java new file mode 100644 index 0000000..8ec972d --- /dev/null +++ b/src/main/java/data/Statistics.java @@ -0,0 +1,299 @@ +package data; + +import java.io.UnsupportedEncodingException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.regex.Pattern; + +import util.Util; +import util.db.RDB; + +public class Statistics { + private CorpusType corpusType; + private AnalysisLevel analysisLevel; + private boolean useDB; + private RDB db; + + private boolean analysisProducedResults; + + private String taxonomy; + private boolean taxonomyIsSet; + + private char JOSType; + private boolean JOSTypeIsSet; + + private String resultTitle; + public Map result = new ConcurrentHashMap<>(); + + // nGrams + private int nGramLevel; + private Integer skip; + private CalculateFor cf; + private List morphosyntacticFilter; + + // distributions + private String distributionTaxonomy; + private char distributionJosWordType; + private boolean vcc; + private Integer substringLength; + + // inflected JOS + private String inflectedJosTaxonomy; + + // GOS + boolean gosOrthMode; + + // šolar + Map solarHeadBlockFilter; + + + // for ngrams + public Statistics(AnalysisLevel al, int nGramLevel, Integer skip, CalculateFor cf) { + String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd.MM.yyyy_hh.mm")); + this.cf = cf; + this.analysisLevel = al; + this.nGramLevel = nGramLevel; + this.skip = skip == null || skip == 0 ? null : skip; + + this.resultTitle = String.format("%s%d-gram_%s_%s", + this.skip != null ? String.format("%d-%s-", skip, "skip") : "", + nGramLevel, + cf.toString(), + dateTime); + } + + // for words distributions + public Statistics(AnalysisLevel al, Taxonomy distributionTaxonomy, GigafidaJosWordType distributionJosWordType, CalculateFor cf) { + String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd.MM.yyyy_hh.mm")); + + this.resultTitle = String.format("%s_%s_%s", + distributionTaxonomy != null ? distributionTaxonomy.toString() : "", + distributionJosWordType != null ? distributionJosWordType.toString() : "", + dateTime); + + this.analysisLevel = al; + this.cf = cf; + this.distributionTaxonomy = distributionTaxonomy != null ? distributionTaxonomy.getTaxonomnyString() : null; + this.taxonomyIsSet = distributionTaxonomy != null; + + this.JOSTypeIsSet = distributionJosWordType != null; + this.distributionJosWordType = this.JOSTypeIsSet ? distributionJosWordType.getWordType() : ' '; + } + + public Statistics(AnalysisLevel al, CalculateFor cf, Integer substringLength) { + String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd.MM.yyyy_hh.mm")); + + this.resultTitle = String.format("%s_%d_%s", + "Distribucija zaporedij samoglasnikov in soglasnikov", + substringLength, + dateTime); + + this.analysisLevel = al; + this.cf = cf; + this.substringLength = substringLength; + this.vcc = true; + } + + public Statistics(AnalysisLevel al, Taxonomy inflectedJosTaxonomy) { + String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd.MM.yyyy_hh.mm")); + + this.resultTitle = String.format("InflectedJOS_%s_%s", + distributionTaxonomy != null ? distributionTaxonomy : "", + dateTime); + + this.analysisLevel = al; + this.inflectedJosTaxonomy = inflectedJosTaxonomy != null ? inflectedJosTaxonomy.getTaxonomnyString() : null; + this.taxonomyIsSet = inflectedJosTaxonomy != null; + } + + public Integer getSkip() { + return skip; + } + + public Integer getSubstringLength() { + return substringLength; + } + + public String getInflectedJosTaxonomy() { + return inflectedJosTaxonomy; + } + + public void setSubstringLength(Integer substringLength) { + this.substringLength = substringLength; + } + + public boolean isVcc() { + return vcc; + } + + public void setVcc(boolean vcc) { + this.vcc = vcc; + } + + public String getDistributionTaxonomy() { + return distributionTaxonomy; + } + + public void setDistributionTaxonomy(String distributionTaxonomy) { + this.distributionTaxonomy = distributionTaxonomy; + } + + public char getDistributionJosWordType() { + return distributionJosWordType; + } + + public void setDistributionJosWordType(char distributionJosWordType) { + this.distributionJosWordType = distributionJosWordType; + } + + public void setMorphosyntacticFilter(List morphosyntacticFilter) { + // change filter strings to regex patterns + this.morphosyntacticFilter = new ArrayList<>(); + for (String s : morphosyntacticFilter) { + this.morphosyntacticFilter.add(Pattern.compile(s.replaceAll("\\*", "."))); + } + } + + public List getMsd() { + return morphosyntacticFilter; + } + + public Map getResult() { + return result; + } + + public void setTaxonomy(String taxonomy) { + this.taxonomy = taxonomy; + } + + public void setTaxonomyIsSet(boolean taxonomyIsSet) { + this.taxonomyIsSet = taxonomyIsSet; + } + + public char getJOSType() { + return JOSType; + } + + public void setJOSType(char JOSType) { + this.JOSType = JOSType; + } + + public boolean isJOSTypeSet() { + return JOSTypeIsSet; + } + + public void setJOSType(boolean JOSTypeIsSet) { + this.JOSTypeIsSet = JOSTypeIsSet; + } + + public void saveResultToDisk(int... limit) throws UnsupportedEncodingException { + // Set>> stats = new HashSet<>(); + // + // if (useDB) { + // result = db.getDump(); + // db.delete(); + // } + // + // // if no results and nothing to save, return false + // if (!(result.size() > 0)) { + // analysisProducedResults = false; + // return; + // } else { + // analysisProducedResults = true; + // } + // + // stats.add(ImmutablePair.of(resultTitle, getSortedResult(result, Util.getValidInt(limit)))); + // Export.SetToCSV(stats); + } + + // private Map getSortedResultInflected(Map map) { + // // first convert to + // Map m = Util.sortByValue(Util.atomicInt2StringAndInt(map), 0); + // + // Map sortedM = new TreeMap<>(); + // + // sortedM.putAll(m); + // + // return sortedM; + // } + + private Map getSortedResult(Map map, int limit) { + return Util.sortByValue(Util.atomicInt2StringAndInt(map), limit); + } + + public String getTaxonomy() { + return taxonomy; + } + + public boolean isTaxonomySet() { + return taxonomyIsSet; + } + + public int getnGramLevel() { + return nGramLevel; + } + + public CalculateFor getCf() { + return cf; + } + + public AnalysisLevel getAnalysisLevel() { + return analysisLevel; + } + + public CorpusType getCorpusType() { + return corpusType; + } + + public void setCorpusType(CorpusType corpusType) { + this.corpusType = corpusType; + } + + public boolean isGosOrthMode() { + return gosOrthMode; + } + + public void setGosOrthMode(boolean gosOrthMode) { + this.gosOrthMode = gosOrthMode; + } + + public Map getSolarHeadBlockFilter() { + return solarHeadBlockFilter; + } + + public void setSolarHeadBlockFilter(Map solarHeadBlockFilter) { + this.solarHeadBlockFilter = solarHeadBlockFilter; + } + + public boolean isUseDB() { + return useDB; + } + + public void setUseDB(boolean useDB) { + if (useDB && db == null) { + db = new RDB(); + } + this.useDB = useDB; + } + + /** + * Stores results from this batch to a database and clears results map + */ + public void storeTmpResultsToDB() { + try { + db.writeBatch(result); + result = new ConcurrentHashMap<>(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + public boolean isAnalysisProducedResults() { + return analysisProducedResults; + } +} diff --git a/src/main/java/data/StatisticsNew.java b/src/main/java/data/StatisticsNew.java new file mode 100644 index 0000000..4e93e7c --- /dev/null +++ b/src/main/java/data/StatisticsNew.java @@ -0,0 +1,409 @@ +package data; + +import static gui.ValidationUtil.*; + +import java.io.UnsupportedEncodingException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import alg.inflectedJOS.WordFormation; +import data.Enums.WordLevelType; +import javafx.collections.ObservableList; +import util.Export; +import util.Util; +import util.db.RDB; + +@SuppressWarnings("Duplicates") +public class StatisticsNew { + public final static Logger logger = LogManager.getLogger(StatisticsNew.class); + + private Corpus corpus; + private Filter filter; + + private String resultTitle; + private Map result; + private Object[][] resultCustom; // for when calculating percentages that don't add up to 100% + private Map> resultNestedSuffix; + private Map> resultNestedPrefix; + private boolean useDB; + private RDB db; + private boolean analysisProducedResults; + private LocalDateTime time; + + public StatisticsNew(Corpus corpus, Filter filter, boolean useDB) { + this.corpus = corpus; + this.filter = filter; + + if (useDB) { + this.useDB = true; + db = new RDB(); + } + + if (filter.getAl() == AnalysisLevel.WORD_LEVEL) { + resultNestedSuffix = new ConcurrentHashMap<>(); + resultNestedPrefix = new ConcurrentHashMap<>(); + } else { + result = new ConcurrentHashMap<>(); + } + + resultTitle = generateResultTitle(); + + logger.debug(toString()); + } + + /** + * Result's title consists of: + *
    + *
  • Corpus type
  • + *
  • Analysis level
  • + *
  • Calculate for
  • + *
  • + *
  • + *
  • + *
  • + *
+ * + * @return + */ + private String generateResultTitle() { + String separator = "_"; + StringBuilder sb = new StringBuilder(); + + if (filter.getAl() == AnalysisLevel.STRING_LEVEL) { + Integer ngramLevel = filter.getNgramValue(); + if(ngramLevel == 0) { + sb.append("Crke"). + append(separator) + .append(corpus.getCorpusType().toString()) + .append(separator); + } else if(ngramLevel == 1) { + sb.append("Besede").append(separator) + .append(corpus.getCorpusType().toString()) + .append(separator); + } + else { + sb.append(filter.getAl().toString()) + .append(separator) + .append(corpus.getCorpusType().toString()) + .append(separator); + sb.append(filter.getCalculateFor().toString()) + .append(separator); + // ngram value + sb.append(filter.getNgramValue()).append("-gram") + .append(separator); + sb.append(filter.getSkipValue()).append("-preskok") + .append(separator); + } + // TODO: assure skip is not null but zero + + } else { + sb.append(filter.getAl().toString()) // analysis level + .append(separator) + .append(corpus.getCorpusType().toString()) + .append(separator); + } + // skip value + // msd ? + // if taxonomy -> taxonomy + // if cvv -> cvv + dolžina + + this.time = this.time != null ? this.time : LocalDateTime.now(); + + sb.append(time.format(DateTimeFormatter.ofPattern("dd.MM.yyyy_hh.mm.ss"))); + return sb.toString(); + + } + + public boolean isAnalysisProducedResults() { + return analysisProducedResults; + } + + public void setAnalysisProducedResults(boolean analysisProducedResults) { + this.analysisProducedResults = analysisProducedResults; + } + + public String toString() { + String newLine = "\n\t- "; + StringBuilder sb = new StringBuilder(); + sb.append(newLine).append("Statistic properties:"); + sb.append(newLine).append(corpus.getCorpusType().toString()).append(String.format(" (%d files)", corpus.getDetectedCorpusFiles().size())); + sb.append(newLine).append(useDB ? "use DB" : "run in memory"); + sb.append(newLine).append(filter.toString()); + + return sb.toString(); + } + + public String getResultTitle() { + return resultTitle; + } + + // **************************************** + // ***************** util ***************** + // **************************************** + + /** + * Stores results from this batch to a database and clears results map + */ + public void storeTmpResultsToDB() { + try { + db.writeBatch(result); + result = new ConcurrentHashMap<>(); + } catch (UnsupportedEncodingException e) { + logger.error("Store tmp results to DB", e); + // e.printStackTrace(); + } + } + + public Filter getFilter() { + return filter; + } + + public Corpus getCorpus() { + return corpus; + } + + public boolean saveResultToDisk(int... limit) throws UnsupportedEncodingException { + Set>> stats = new HashSet<>(); + + if (useDB) { + result = db.getDump(); + db.delete(); + } + + // if no results and nothing to save, return false + if (!(result.size() > 0)) { + analysisProducedResults = false; + return false; + } else { + analysisProducedResults = true; + } + + stats.add(ImmutablePair.of(resultTitle, getSortedResult(result, Util.getValidInt(limit)))); + Export.SetToCSV(stats, corpus.getChosenResultsLocation(), headerInfoBlock()); + return true; + } + + public boolean saveResultNestedToDisk(int... limit) throws UnsupportedEncodingException { + resultTitle = generateResultTitle(); + + if (useDB) { + result = db.getDump(); + db.delete(); + } + Map>> results = new HashMap<>(); + + if (!isEmpty(resultNestedSuffix)) { + results.put(WordLevelType.SUFFIX, sortNestedMap(resultNestedSuffix, Util.getValidInt(limit))); + } + + if (!isEmpty(resultNestedPrefix)) { + results.put(WordLevelType.PREFIX, sortNestedMap(resultNestedPrefix, Util.getValidInt(limit))); + } + + // if no results and nothing to save, return false + if (!(results.size() > 0)) { + analysisProducedResults = false; + return false; + } else { + analysisProducedResults = true; + } + + Export.nestedMapToCSV(resultTitle, results, corpus.getChosenResultsLocation(), headerInfoBlock()); + return true; + } + + public boolean recalculateAndSaveResultToDisk() throws UnsupportedEncodingException { + filter.setAl(AnalysisLevel.WORD_FORMATION); + resultTitle = generateResultTitle(); + + if (useDB) { + result = db.getDump(); + db.delete(); + } + + // if no results and nothing to save, return false + if (!(result.size() > 0)) { + analysisProducedResults = false; + return false; + } else { + analysisProducedResults = true; + } + + WordFormation.calculateStatistics(this); + + Export.SetToCSV(resultTitle, resultCustom, corpus.getChosenResultsLocation(), headerInfoBlock()); + return true; + } + + private Map> sortNestedMap(Map> nestedMap, int limit) { + Map> sorted = new HashMap<>(); + + for (String s : nestedMap.keySet()) { + sorted.put(s, getSortedResult(nestedMap.get(s), Util.getValidInt(limit))); + } + + return sorted; + } + + + private Map getSortedResult(Map map, int limit) { + return Util.sortByValue(Util.atomicInt2StringAndInt(map), limit); + } + + public void updateResults(String o) { + // if not in map + AtomicLong r = result.putIfAbsent(o, new AtomicLong(1)); + + // else + if (r != null) + result.get(o).incrementAndGet(); + } + + public Map getResult() { + return result; + } + + public Object[][] getResultCustom() { + return resultCustom; + } + + public void setResultCustom(Object[][] resultCustom) { + this.resultCustom = resultCustom; + } + + public void updateResultsNested(WordLevelType type, String key, String stringValue) { + ConcurrentHashMap> resultsMap; + + if (type == WordLevelType.SUFFIX) { + updateResultsNestedSuffix(key, stringValue); + } else if (type == WordLevelType.PREFIX) { + updateResultsNestedPrefix(key, stringValue); + } + } + + public void updateResultsNestedSuffix(String key, String stringValue) { + if (resultNestedSuffix.containsKey(key)) { + // if not in map + AtomicLong r = resultNestedSuffix.get(key).putIfAbsent(stringValue, new AtomicLong(1)); + + // else + if (r != null) { + resultNestedSuffix.get(key).get(stringValue).incrementAndGet(); + } + } else { + resultNestedSuffix.putIfAbsent(key, new ConcurrentHashMap<>()); + AtomicLong r = resultNestedSuffix.get(key).putIfAbsent(stringValue, new AtomicLong(1)); + + if (r != null) { + resultNestedSuffix.get(key).get(stringValue).incrementAndGet(); + } + } + } + + public void updateResultsNestedPrefix(String key, String stringValue) { + if (resultNestedPrefix.containsKey(key)) { + // if not in map + AtomicLong r = resultNestedPrefix.get(key).putIfAbsent(stringValue, new AtomicLong(1)); + + // else + if (r != null) { + resultNestedPrefix.get(key).get(stringValue).incrementAndGet(); + } + } else { + resultNestedPrefix.putIfAbsent(key, new ConcurrentHashMap<>()); + AtomicLong r = resultNestedPrefix.get(key).putIfAbsent(stringValue, new AtomicLong(1)); + + if (r != null) { + resultNestedPrefix.get(key).get(stringValue).incrementAndGet(); + } + } + } + + private LinkedHashMap headerInfoBlock() { + LinkedHashMap info = new LinkedHashMap<>(); + + info.put("Korpus:", corpus.getCorpusType().toString()); + info.put("Datum:", time.format(DateTimeFormatter.ofPattern("dd.MM.yyyy hh:mm"))); + if (filter.getAl() == AnalysisLevel.STRING_LEVEL) { + Integer ngramLevel = filter.getNgramValue(); + if (ngramLevel == 0) + info.put("Analiza:", "Črke"); + else if (ngramLevel == 1) + info.put("Analiza", "Besede"); + else + info.put("Analiza:", filter.getAl().toString()); + } else { + info.put("Analiza:", filter.getAl().toString()); + } + + if (filter.getAl() == AnalysisLevel.STRING_LEVEL) { + Integer ngramLevel = filter.getNgramValue(); + + // n.gram nivo + if (ngramLevel > 1) { + info.put("n-gram nivo:", String.valueOf(ngramLevel)); + } else if (ngramLevel == 1){ + info.put("n-gram nivo:", "nivo besed"); + } else { + info.put("n-gram nivo:", "nivo črk"); + } + // skip + if (ngramLevel > 1) + info.put("Skip:", isNotEmpty(filter.getSkipValue()) ? filter.getSkipValue().toString() : "0"); + + // izračunaj za + info.put("Izračunaj za:", filter.getCalculateFor().toString()); + + // msd + if (!isEmpty(filter.getMsd())) { + StringBuilder msdPattern = new StringBuilder(); + for (Pattern pattern : filter.getMsd()) { + msdPattern.append(pattern.toString()).append(" "); + } + + info.put("MSD:", msdPattern.toString()); + } + + // taksonomija + if (!isEmpty(filter.getTaxonomy())) { + info.put("Taksonomija:", StringUtils.join(filter.getTaxonomy(), ", ")); + } + + + } + + if (isNotEmpty(filter.getTaxonomy()) && Tax.getCorpusTypesWithTaxonomy().contains(corpus.getCorpusType())) { + ArrayList tax = Tax.getTaxonomyForInfo(corpus.getCorpusType(), filter.getTaxonomy()); + + info.put("Taksonomija: ", ""); + String sep = ""; + for (String s : tax) { + info.put(sep = sep + " ", s); + } + } + + if (corpus.getCorpusType() == CorpusType.SOLAR) { + HashMap> filters = corpus.getSolarFilters(); + + if (!isEmpty(filters)) { + info.put("Dodatni filtri: ", ""); + + for (Map.Entry> f : filters.entrySet()) { + info.put(f.getKey(), StringUtils.join(f.getValue(), ", ")); + } + } + } + + return info; + } +} diff --git a/src/main/java/data/Tax.java b/src/main/java/data/Tax.java new file mode 100644 index 0000000..c1d6251 --- /dev/null +++ b/src/main/java/data/Tax.java @@ -0,0 +1,175 @@ +package data; + +import java.util.*; +import java.util.stream.Collectors; + +import gui.ValidationUtil; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +public class Tax { + private static LinkedHashMap GIGAFIDA_TAXONOMY; + private static LinkedHashMap GOS_TAXONOMY; + private static final HashSet corpusTypesWithTaxonomy = new HashSet<>(Arrays.asList(CorpusType.GIGAFIDA, CorpusType.GOS, CorpusType.CCKRES)); + + static { + // GIGAFIDA ---------------------------- + GIGAFIDA_TAXONOMY = new LinkedHashMap<>(); + + GIGAFIDA_TAXONOMY.put("SSJ.T", "tisk"); + GIGAFIDA_TAXONOMY.put("SSJ.T.K", "tisk-knjižno"); + GIGAFIDA_TAXONOMY.put("SSJ.T.K.L", "tisk-knjižno-leposlovno"); + GIGAFIDA_TAXONOMY.put("SSJ.T.K.S", "tisk-knjižno-strokovno"); + GIGAFIDA_TAXONOMY.put("SSJ.T.P", "tisk-periodično"); + GIGAFIDA_TAXONOMY.put("SSJ.T.P.C", "tisk-periodično-časopis"); + GIGAFIDA_TAXONOMY.put("SSJ.T.P.R", "tisk-periodično-revija"); + GIGAFIDA_TAXONOMY.put("SSJ.T.D", "tisk-drugo"); + GIGAFIDA_TAXONOMY.put("SSJ.I", "internet"); + + GIGAFIDA_TAXONOMY.put("Ft.P", "prenosnik"); + GIGAFIDA_TAXONOMY.put("Ft.P.G", "prenosnik-govorni"); + GIGAFIDA_TAXONOMY.put("Ft.P.E", "prenosnik-elektronski"); + GIGAFIDA_TAXONOMY.put("Ft.P.P", "prenosnik-pisni"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.O", "prenosnik-pisni-objavljeno"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.O.K", "prenosnik-pisni-objavljeno-knjižno"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.O.P", "prenosnik-pisni-objavljeno-periodično"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.O.P.C", "prenosnik-pisni-objavljeno-periodično-časopisno"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.O.P.C.D", "prenosnik-pisni-objavljeno-periodično-časopisno-dnevno"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.O.P.C.V", "prenosnik-pisni-objavljeno-periodično-časopisno-večkrat tedensko"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.O.P.C.T", "prenosnik-pisni-objavljeno-periodično-časopisno-tedensko"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.O.P.R", "prenosnik-pisni-objavljeno-periodično-revialno"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.O.P.R.T", "prenosnik-pisni-objavljeno-periodično-revialno-tedensko"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.O.P.R.S", "prenosnik-pisni-objavljeno-periodično-revialno-štirinajstdnevno"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.O.P.R.M", "prenosnik-pisni-objavljeno-periodično-revialno-mesečno"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.O.P.R.D", "prenosnik-pisni-objavljeno-periodično-revialno-redkeje kot na mesec"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.O.P.R.O", "prenosnik-pisni-objavljeno-periodično-revialno-občasno"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.N", "prenosnik-pisni-neobjavljeno"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.N.J", "prenosnik-pisni-neobjavljeno-javno"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.N.I", "prenosnik-pisni-neobjavljeno-interno"); + GIGAFIDA_TAXONOMY.put("Ft.P.P.N.Z", "prenosnik-pisni-neobjavljeno-zasebno"); + + GIGAFIDA_TAXONOMY.put("Ft.Z", "zvrst"); + GIGAFIDA_TAXONOMY.put("Ft.Z.U", "zvrst-umetnostna"); + GIGAFIDA_TAXONOMY.put("Ft.Z.U.P", "zvrst-umetnostna-pesniška"); + GIGAFIDA_TAXONOMY.put("Ft.Z.U.R", "zvrst-umetnostna-prozna"); + GIGAFIDA_TAXONOMY.put("Ft.Z.U.D", "zvrst-umetnostna-dramska"); + GIGAFIDA_TAXONOMY.put("Ft.Z.N", "zvrst-neumetnostna"); + GIGAFIDA_TAXONOMY.put("Ft.Z.N.S", "zvrst-neumetnostna-strokovna"); + GIGAFIDA_TAXONOMY.put("Ft.Z.N.S.H", "zvrst-neumetnostna-strokovna-humanistična in družboslovna"); + GIGAFIDA_TAXONOMY.put("Ft.Z.N.S.N", "zvrst-neumetnostna-strokovna-naravoslovna in tehnična"); + GIGAFIDA_TAXONOMY.put("Ft.Z.N.N", "zvrst-neumetnostna-nestrokovna"); + GIGAFIDA_TAXONOMY.put("Ft.Z.N.P", "zvrst-neumetnostna-pravna"); + GIGAFIDA_TAXONOMY.put("Ft.L", "zvrst-lektorirano"); + GIGAFIDA_TAXONOMY.put("Ft.L.D", "zvrst-lektorirano-da"); + GIGAFIDA_TAXONOMY.put("Ft.L.N", "zvrst-lektorirano-ne"); + + // GOS ---------------------------------- + GOS_TAXONOMY = new LinkedHashMap<>(); + + GOS_TAXONOMY.put("gos.T", "diskurz"); + GOS_TAXONOMY.put("gos.T.J", "diskurz-javni"); + GOS_TAXONOMY.put("gos.T.J.I", "diskurz-javni-informativno-izobraževalni"); + GOS_TAXONOMY.put("gos.T.J.R", "diskurz-javni-razvedrilni"); + GOS_TAXONOMY.put("gos.T.N", "diskurz-nejavni"); + GOS_TAXONOMY.put("gos.T.N.N", "diskurz-nejavni-nezasebni"); + GOS_TAXONOMY.put("gos.T.N.Z", "diskurz-nejavni-zasebni"); + + GOS_TAXONOMY.put("gos.S", "situacija"); + GOS_TAXONOMY.put("gos.S.R", "situacija-radio"); + GOS_TAXONOMY.put("gos.S.T", "situacija-televizija"); + } + + /** + * Returns the whole default taxonomy for the specified corpus type + */ + public static ObservableList getTaxonomyForComboBox(CorpusType corpusType) { + if (corpusType == CorpusType.GIGAFIDA || corpusType == CorpusType.CCKRES) { + return FXCollections.observableArrayList(GIGAFIDA_TAXONOMY.values()); + } else if (corpusType == CorpusType.GOS) { + return FXCollections.observableArrayList(GOS_TAXONOMY.values()); + } + + return FXCollections.observableArrayList(new ArrayList<>()); + } + + /** + * Returns taxonomy names only for items found in headers + */ + public static ObservableList getTaxonomyForComboBox(CorpusType corpusType, HashSet foundTax) { + LinkedHashMap tax = new LinkedHashMap<>(); + + if (corpusType == CorpusType.GIGAFIDA || corpusType == CorpusType.CCKRES) { + tax = GIGAFIDA_TAXONOMY; + } else if (corpusType == CorpusType.GOS) { + tax = GOS_TAXONOMY; + } + + ArrayList taxForCombo = new ArrayList<>(); + + // assures same relative order + for (String t : tax.keySet()) { + if (foundTax.contains(t)) { + taxForCombo.add(tax.get(t)); + } + } + + return FXCollections.observableArrayList(taxForCombo); + } + + public static HashSet getCorpusTypesWithTaxonomy() { + return corpusTypesWithTaxonomy; + } + + public static ArrayList getTaxonomyCodes(ArrayList taxonomyNames, CorpusType corpusType) { + ArrayList result = new ArrayList<>(); + + if (ValidationUtil.isEmpty(taxonomyNames)) { + return result; + } + + LinkedHashMap tax = new LinkedHashMap<>(); + + if (corpusType == CorpusType.GIGAFIDA || corpusType == CorpusType.CCKRES) { + tax = GIGAFIDA_TAXONOMY; + } else if (corpusType == CorpusType.GOS) { + tax = GOS_TAXONOMY; + } + + // for easier lookup + Map taxInversed = tax.entrySet() + .stream() + .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); + + for (String taxonomyName : taxonomyNames) { + result.add(taxInversed.get(taxonomyName)); + } + + return result; + } + + /** + * Returns a list of proper names for codes + * + * @param corpusType + * @param taxonomy + * + * @return + */ + public static ArrayList getTaxonomyForInfo(CorpusType corpusType, ArrayList taxonomy) { + LinkedHashMap tax = new LinkedHashMap<>(); + + if (corpusType == CorpusType.GIGAFIDA || corpusType == CorpusType.CCKRES) { + tax = GIGAFIDA_TAXONOMY; + } else if (corpusType == CorpusType.GOS) { + tax = GOS_TAXONOMY; + } + + ArrayList result = new ArrayList<>(); + + for (String t : taxonomy) { + result.add(tax.get(t)); + } + + return result; + } +} diff --git a/src/main/java/data/Taxonomy.java b/src/main/java/data/Taxonomy.java new file mode 100644 index 0000000..d6d408e --- /dev/null +++ b/src/main/java/data/Taxonomy.java @@ -0,0 +1,171 @@ +package data; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.Collectors; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +public enum Taxonomy { + // GOS + JAVNI("javni", "T.J", "gos"), + INFORMATIVNO_IZOBRAZEVALNI("informativno-izobraževalni", "T.J.I", "gos"), + RAZVEDRILNI("razvedrilni", "T.J.R", "gos"), + NEJAVNI("nejavni", "T.N", "gos"), + NEZASEBNI("nezasebni", "T.N.N", "gos"), + ZASEBNI("zasebni", "T.N.Z", "gos"), + OSEBNI_STIK("osebni stik", "K.O", "gos"), + TELEFON("telefon", "K.P", "gos"), + RADIO("radio", "K.R", "gos"), + TELEVIZIJA("televizija", "K.T", "gos"), + // Gigafida + KNJIZNO("knjižno", "T.K", "gigafida"), + LEPOSLOVNO("leposlovno", "T.K.L", "gigafida"), + STROKOVNO("strokovno", "T.K.S", "gigafida"), + PERIODICNO("periodično", "T.P", "gigafida"), + CASOPIS("časopis", "T.P.C", "gigafida"), + REVIJA("revija", "T.P.R", "gigafida"), + INTERNET("internet", "I", "gigafida"), + + SSJ_TISK("tisk", "SSJ.T", "gigafida"), + SSJ_KNJIZNO("opis", "identifikator", "gigafida"), + SSJ_LEPOSLOVNO("opis", "identifikator", "gigafida"), + SSJ_STROKOVNO("opis", "identifikator", "gigafida"), + SSJ_PERIODICNO("opis", "identifikator", "gigafida"), + SSJ_CASOPIS("opis", "identifikator", "gigafida"), + SSJ_REVIJA("opis", "identifikator", "gigafida"), + SSJ_DRUGO("opis", "identifikator", "gigafida"), + SSJ_INTERNET("opis", "identifikator", "gigafida"), + FT_P_PRENOSNIK("opis", "identifikator", "gigafida"), + FT_P_GOVORNI("opis", "identifikator", "gigafida"), + FT_P_ELEKTRONSKI("opis", "identifikator", "gigafida"), + FT_P_PISNI("opis", "identifikator", "gigafida"), + FT_P_OBJAVLJENO("opis", "identifikator", "gigafida"), + FT_P_KNJIZNO("opis", "identifikator", "gigafida"), + FT_P_PERIODICNO("opis", "identifikator", "gigafida"), + FT_P_CASOPISNO("opis", "identifikator", "gigafida"), + FT_P_DNEVNO("opis", "identifikator", "gigafida"), + FT_P_VECKRAT_TEDENSKO("opis", "identifikator", "gigafida"), + // FT_P_TEDENSKO("opis", "identifikator", "gigafida"), + FT_P_REVIALNO("opis", "identifikator", "gigafida"), + FT_P_TEDENSKO("opis", "identifikator", "gigafida"), + FT_P_STIRINAJSTDNEVNO("opis", "identifikator", "gigafida"), + FT_P_MESECNO("opis", "identifikator", "gigafida"), + FT_P_REDKEJE_KOT_MESECNO("opis", "identifikator", "gigafida"), + FT_P_OBCASNO("opis", "identifikator", "gigafida"), + FT_P_NEOBJAVLJENO("opis", "identifikator", "gigafida"), + FT_P_JAVNO("opis", "identifikator", "gigafida"), + FT_P_INTERNO("opis", "identifikator", "gigafida"), + FT_P_ZASEBNO("opis", "identifikator", "gigafida"), + FT_ZVRST("opis", "identifikator", "gigafida"), + FT_UMETNOSTNA("opis", "identifikator", "gigafida"), + FT_PESNISKA("opis", "identifikator", "gigafida"), + FT_PROZNA("opis", "identifikator", "gigafida"), + FT_DRAMSKA("opis", "identifikator", "gigafida"), + FT_NEUMETNOSTNA("opis", "identifikator", "gigafida"), + FT_STROKOVNA("opis", "identifikator", "gigafida"), + FT_HID("opis", "identifikator", "gigafida"), + FT_NIT("opis", "identifikator", "gigafida"), + FT_NESTROKOVNA("opis", "identifikator", "gigafida"), + FT_PRAVNA("opis", "identifikator", "gigafida"), + FT_LEKTORIRANO("opis", "identifikator", "gigafida"), + FT_DA("opis", "identifikator", "gigafida"), + FT_NE("opis", "identifikator", "gigafida"); + + + + private final String name; + private final String taxonomy; + private final String corpus; + + Taxonomy(String name, String taxonomy, String corpusType) { + this.name = name; + this.taxonomy = taxonomy; + this.corpus = corpusType; + } + + public String toString() { + return this.name; + } + + public String getTaxonomnyString() { + return this.taxonomy; + } + + public static Taxonomy factory(String tax) { + if (tax != null) { + // GOS + if (JAVNI.toString().equals(tax)) { + return JAVNI; + } + if (INFORMATIVNO_IZOBRAZEVALNI.toString().equals(tax)) { + return INFORMATIVNO_IZOBRAZEVALNI; + } + if (RAZVEDRILNI.toString().equals(tax)) { + return RAZVEDRILNI; + } + if (NEJAVNI.toString().equals(tax)) { + return NEJAVNI; + } + if (NEZASEBNI.toString().equals(tax)) { + return NEZASEBNI; + } + if (ZASEBNI.toString().equals(tax)) { + return ZASEBNI; + } + if (OSEBNI_STIK.toString().equals(tax)) { + return OSEBNI_STIK; + } + if (TELEFON.toString().equals(tax)) { + return TELEFON; + } + if (RADIO.toString().equals(tax)) { + return RADIO; + } + if (TELEVIZIJA.toString().equals(tax)) { + return TELEVIZIJA; + } + + // Gigafida + // if (TISK.toString().equals(tax)) { + // return TISK; + // } + if (KNJIZNO.toString().equals(tax)) { + return KNJIZNO; + } + if (LEPOSLOVNO.toString().equals(tax)) { + return LEPOSLOVNO; + } + if (STROKOVNO.toString().equals(tax)) { + return STROKOVNO; + } + if (PERIODICNO.toString().equals(tax)) { + return PERIODICNO; + } + if (CASOPIS.toString().equals(tax)) { + return CASOPIS; + } + if (REVIJA.toString().equals(tax)) { + return REVIJA; + } + if (INTERNET.toString().equals(tax)) { + return INTERNET; + } + } + return null; + } + + public static ObservableList getDefaultForComboBox(String corpusType) { + ArrayList values = Arrays.stream(Taxonomy.values()) + .filter(x -> x.corpus.equals(corpusType)) + .map(x -> x.name) + .collect(Collectors.toCollection(ArrayList::new)); + + return FXCollections.observableArrayList(values); + } + + public static ObservableList getDefaultForComboBox(CorpusType corpusType) { + return getDefaultForComboBox(corpusType.toString()); + } +} diff --git a/src/main/java/data/Validation.java b/src/main/java/data/Validation.java new file mode 100644 index 0000000..44b809e --- /dev/null +++ b/src/main/java/data/Validation.java @@ -0,0 +1,53 @@ +package data; + +import static gui.ValidationUtil.*; + +import java.util.ArrayList; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; + +import gui.Messages; +import gui.ValidationUtil; + +public class Validation { + + public static String validateForStringLevel(Filter filter) { + ArrayList errors = new ArrayList<>(); + + // should not be null, error if null, because init failed + if (filter.getNgramValue() == null) { + errors.add(Messages.MISSING_NGRAM_LEVEL); + } + + // should not be null, error if null, because init failed + if (filter.getCalculateFor() == null) { + errors.add(Messages.MISSING_CALCULATE_FOR); + } + + if (filter.getSkipValue() == null) { + filter.setSkipValue(0); + } + + if (filter.getNgramValue() != null && ValidationUtil.isEmpty(filter.getMsd()) && + (filter.getMsd().size() != filter.getNgramValue())) { + if (!(filter.getMsd().size() == 1 && filter.getNgramValue() == 0) && !ValidationUtil.isEmpty(filter.getMsd())) + errors.add(Messages.WARNING_MISMATCHED_NGRAM_AND_TOKENS_VALUES); + } + + Integer ngramValue = filter.getNgramValue(); + ArrayList msd = filter.getMsd(); + + if (ngramValue > 0 && !ValidationUtil.isEmpty(msd) && ngramValue != msd.size()) { + errors.add(String.format(Messages.WARNING_MISMATCHED_NGRAM_AND_TOKENS_VALUES, ngramValue, msd.size())); + } + + if (filter.getNgramValue() != null && filter.getNgramValue() == 0 && isEmpty(filter.getStringLength())) { + // if count letters, make sure that the length is given + // TODO: check that words we're adding in xml reader are longer than this value + errors.add(Messages.MISSING_STRING_LENGTH); + } + + return isEmpty(errors) ? null : StringUtils.join(errors, ", \n"); + } +} diff --git a/src/main/java/data/Word.java b/src/main/java/data/Word.java new file mode 100644 index 0000000..154dd24 --- /dev/null +++ b/src/main/java/data/Word.java @@ -0,0 +1,141 @@ +package data; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashSet; + +import org.apache.commons.lang3.StringUtils; + +import data.Enums.Msd; +import gui.ValidationUtil; + +public class Word implements Serializable { + public static final char PAD_CHARACTER = '-'; + + private String word; + private String lemma; + private String msd; + private final HashSet VOWELS = new HashSet<>(Arrays.asList('a', 'e', 'i', 'o', 'u')); + + /** + * Possible values: + *

+ *

    + *
  • S = samostalnik
  • + *
  • G = glagol
  • + *
  • P = pridevnik
  • + *
  • R = prislov
  • + *
  • Z = zaimek
  • + *
  • K = števnik
  • + *
  • D = predlog
  • + *
  • V = veznik
  • + *
  • L = členek
  • + *
  • M = medmet
  • + *
  • O = okrajšava
  • + *
  • N = neuvrščeno
  • + *
+ */ + //private char besedna_vrsta; + public Word(String word, String lemma, String msd) { + this.lemma = lemma; + this.msd = normalizeMsd(msd); + + // veliko zacetnico ohranimo samo za lastna imena + if (!ValidationUtil.isEmpty(this.msd) && !(this.msd.charAt(0) == 'S' + && this.msd.length() >= 2 + && this.msd.charAt(1) == 'l')) { + this.word = word.toLowerCase(); + } else { + this.word = word; + } + } + + public Word() { + } + + /** + * Appends a number of '-' to msds which are not properly sized. + * E.g. nouns should have 5 attributes, yet the last one isn't always defined (Somei vs. Sometd) + * + * @param msdInput + * + * @return + */ + private String normalizeMsd(String msdInput) { + if (ValidationUtil.isEmpty(msdInput)) { + return ""; + } else { + return StringUtils.rightPad(msdInput, Msd.getMsdLengthForType(msdInput), PAD_CHARACTER); + } + } + + public Word(String word) { + this.word = word; + } + + public String getWord() { + return word; + } + + public String getCVVWord() { + return covertToCvv(word); + } + + public String getCVVLemma() { + return covertToCvv(lemma); + } + + private String covertToCvv(String s) { + char[] StringCA = s.toCharArray(); + + for (int i = 0; i < StringCA.length; i++) { + StringCA[i] = VOWELS.contains(StringCA[i]) ? 'V' : 'C'; + } + + return new String(StringCA); + } + + public void setWord(String word) { + this.word = word; + } + + public String getLemma() { + return lemma; + } + + public void setLemma(String lemma) { + this.lemma = lemma; + } + + public String getMsd() { + return msd; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("beseda:\t") + .append(getWord()) + .append("\n") + .append("lema:\t") + .append(getLemma()) + .append("\n") + .append("msd:\t") + .append(getMsd()) + .append("\n"); + + return sb.toString(); + } + + public String getForCf(CalculateFor calculateFor, boolean cvv) { + String returnValue = ""; + + if (cvv) { + returnValue = calculateFor == CalculateFor.WORD ? getCVVWord() : getCVVLemma(); + } else { + returnValue = calculateFor == CalculateFor.WORD ? getWord() : getLemma(); + } + + return returnValue; + } +} diff --git a/src/main/java/gui/CharacterAnalysisTab.java b/src/main/java/gui/CharacterAnalysisTab.java new file mode 100644 index 0000000..cd1f6e3 --- /dev/null +++ b/src/main/java/gui/CharacterAnalysisTab.java @@ -0,0 +1,454 @@ +package gui; + +import data.*; +import javafx.application.HostServices; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.concurrent.Task; +import javafx.fxml.FXML; +import javafx.scene.control.*; +import javafx.scene.layout.Pane; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.controlsfx.control.CheckComboBox; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.util.*; +import java.util.regex.Pattern; + +import static alg.XML_processing.readXML; +import static gui.GUIController.showAlert; +import static gui.Messages.*; + +@SuppressWarnings("Duplicates") +public class CharacterAnalysisTab { + public final static Logger logger = LogManager.getLogger(CharacterAnalysisTab.class); + + @FXML + public Label selectedFiltersLabel; + @FXML + public Label solarFilters; + + @FXML + private TextField msdTF; + private ArrayList msd; + private ArrayList msdStrings; + + @FXML + private CheckComboBox taxonomyCCB; + private ArrayList taxonomy; + + @FXML + private CheckBox calculatecvvCB; + private boolean calculateCvv; + + @FXML + private TextField stringLengthTF; + private Integer stringLength; + + @FXML + private ToggleGroup calculateForRB; + private CalculateFor calculateFor; + + @FXML + private RadioButton lemmaRB; + + @FXML + private RadioButton varietyRB; + + @FXML + private Pane paneLetters; + + @FXML + private Button computeNgramsB; + + @FXML + public ProgressBar ngramProgressBar; + @FXML + public Label progressLabel; + + @FXML + private Hyperlink helpH; + + private enum MODE { + LETTER + } + + private MODE currentMode; + + private Corpus corpus; + private HashMap> solarFiltersMap; + private Filter filter; + private boolean useDb; + private HostServices hostService; + + private static final ObservableList N_GRAM_COMPUTE_FOR_LETTERS = FXCollections.observableArrayList("različnica", "lema"); + private static final ObservableList N_GRAM_COMPUTE_FOR_WORDS_ORTH = FXCollections.observableArrayList("različnica"); + + + // TODO: pass observables for taxonomy based on header scan + // after header scan + private ObservableList taxonomyCCBValues; + private CorpusType currentCorpusType; + + public void init() { + currentMode = MODE.LETTER; + toggleMode(currentMode); + + calculateForRB.selectedToggleProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Toggle oldValue, Toggle newValue) { + //logger.info("calculateForRB:", newValue.toString()); + RadioButton chk = (RadioButton)newValue.getToggleGroup().getSelectedToggle(); // Cast object to radio button + calculateFor = CalculateFor.factory(chk.getText()); + logger.info("calculateForRB:", chk.getText()); + //System.out.println("Selected Radio Button - "+chk.getText()); + } + }); + + // msd + msdTF.focusedProperty().addListener((observable, oldValue, newValue) -> { + if (!newValue) { + // focus lost + String value = msdTF.getText(); + logger.info("msdTf: ", value); + + if (!ValidationUtil.isEmpty(value)) { + ArrayList msdTmp = new ArrayList<>(Arrays.asList(value.split(" "))); + + int nOfRequiredMsdTokens = 1; + if (msdTmp.size() != nOfRequiredMsdTokens) { + String msg = String.format(Messages.WARNING_MISMATCHED_NGRAM_AND_TOKENS_VALUES, nOfRequiredMsdTokens, msdTmp.size()); + logAlert(msg); + showAlert(Alert.AlertType.ERROR, msg); + } + msd = new ArrayList<>(); + msdStrings = new ArrayList<>(); + for (String msdToken : msdTmp) { + msd.add(Pattern.compile(msdToken)); + msdStrings.add(msdToken); + } + logger.info(String.format("msd accepted (%d)", msd.size())); + + } else if (!ValidationUtil.isEmpty(newValue)) { + msd = new ArrayList<>(); + msdStrings = new ArrayList<>(); + } + } + }); + + msdTF.setText(""); + msd = new ArrayList<>(); + + // taxonomy + if (Tax.getCorpusTypesWithTaxonomy().contains(corpus.getCorpusType())) { + taxonomyCCB.getItems().removeAll(); + taxonomyCCB.getItems().setAll(corpus.getTaxonomy()); + taxonomyCCB.getCheckModel().getCheckedItems().addListener((ListChangeListener) c -> { + taxonomy = new ArrayList<>(); + ObservableList checkedItems = taxonomyCCB.getCheckModel().getCheckedItems(); + taxonomy.addAll(checkedItems); + logger.info(String.format("Selected taxonomy: %s", StringUtils.join(checkedItems, ","))); + }); + taxonomyCCB.getCheckModel().clearChecks(); + } else { + taxonomyCCB.setDisable(true); + } + + // cvv + calculatecvvCB.selectedProperty().addListener((observable, oldValue, newValue) -> { + calculateCvv = newValue; + logger.info("calculate cvv: " + calculateCvv); + }); + + + // string length + stringLengthTF.focusedProperty().addListener((observable, oldValue, newValue) -> { + if (!newValue) { + // focus lost + String value = stringLengthTF.getText(); + if (!ValidationUtil.isEmpty(value)) { + if (!ValidationUtil.isNumber(value)) { + logAlert("stringlengthTf: " + WARNING_ONLY_NUMBERS_ALLOWED); + GUIController.showAlert(Alert.AlertType.ERROR, WARNING_ONLY_NUMBERS_ALLOWED); + } + stringLength = Integer.parseInt(value); + } else { + GUIController.showAlert(Alert.AlertType.ERROR, WARNING_MISSING_STRING_LENGTH); + stringLengthTF.setText("1"); + logAlert(WARNING_MISSING_STRING_LENGTH); + } + } + }); + + computeNgramsB.setOnAction(e -> { + compute(); + logger.info("compute button"); + }); + + helpH.setOnAction(e -> openHelpWebsite()); + } + + /** + * case a: values for combo boxes can change after a corpus change + *
    + *
  • different corpus type - reset all fields so no old values remain
  • + *
  • same corpus type, different subset - keep
  • + *
+ *

+ * case b: values for combo boxes can change after a header scan + *

    + *
  • at first, fields are populated by corpus type defaults
  • + *
  • after, with gathered data
  • + *
+ *

+ * ngrams: 1 + * calculateFor: word + * msd: + * taxonomy: + * skip: 0 + * iscvv: false + * string length: 1 + */ + public void populateFields() { + // corpus changed if: current one is null (this is first run of the app) + // or if currentCorpus != gui's corpus + boolean corpusChanged = currentCorpusType == null + || currentCorpusType != corpus.getCorpusType(); + + // TODO: check for GOS, GIGAFIDA, SOLAR... + // refresh and: + // TODO if current value != null && is in new calculateFor ? keep : otherwise reset + if (calculateFor == null) { + calculateForRB.selectToggle(lemmaRB); + calculateFor = CalculateFor.factory(calculateForRB.getSelectedToggle().toString()); + } + + if (!filter.hasMsd()) { + // if current corpus doesn't have msd data, disable this field + msd = new ArrayList<>(); + msdTF.setText(""); + msdTF.setDisable(true); + logger.info("no msd data"); + } else { + if (ValidationUtil.isEmpty(msd) + || (!ValidationUtil.isEmpty(msd) && corpusChanged)) { + // msd has not been set previously + // or msd has been set but the corpus changed -> reset + msd = new ArrayList<>(); + msdTF.setText(""); + msdTF.setDisable(false); + logger.info("msd reset"); + } else if (!ValidationUtil.isEmpty(msd) && !corpusChanged) { + // if msd has been set, but corpus type remained the same, we can keep any set msd value + msdTF.setText(StringUtils.join(msdStrings, " ")); + msdTF.setDisable(false); + logger.info("msd kept"); + } + } + + // TODO: taxonomy: refresh and keep if in new taxonomy, otherwise empty (no selection) + + // keep calculateCvv + calculatecvvCB.setSelected(calculateCvv); + + // keep string length if set + if (stringLength != null) { + stringLengthTF.setText(String.valueOf(stringLength)); + } else { + stringLengthTF.setText("1"); + stringLength = 1; + } + + // TODO: trigger on rescan + if ((currentCorpusType != null && currentCorpusType != corpus.getCorpusType())) { + // user changed corpus (by type) or by selection & triggered a rescan of headers + // see if we read taxonomy from headers, otherwise use default values for given corpus + ObservableList tax = corpus.getTaxonomy(); + taxonomyCCBValues = tax != null ? tax : Taxonomy.getDefaultForComboBox(corpus.getCorpusType()); + + currentCorpusType = corpus.getCorpusType(); + // setTaxonomyIsDirty(false); + } else { + + } + + // see if we read taxonomy from headers, otherwise use default values for given corpus + ObservableList tax = corpus.getTaxonomy(); + taxonomyCCBValues = tax != null ? tax : Taxonomy.getDefaultForComboBox(corpus.getCorpusType()); + taxonomyCCB.getItems().addAll(taxonomyCCBValues); + + } + + /** + * Toggles visibility for panes which hold fields for skipgram value (not applicable when calculating for letters) etc., + * sets combobox values to what is applicable ... + * + * @param mode + */ + public void toggleMode(MODE mode) { + if (mode == null) { + mode = currentMode; + } + + logger.info("mode: ", mode.toString()); + + if (mode == MODE.LETTER) { + paneLetters.setVisible(true); + + // populate with default cvv length value + if (stringLength == null) { + stringLengthTF.setText("1"); + stringLength = 1; + } else { + stringLengthTF.setText(String.valueOf(stringLength)); + } + + // if calculateFor was selected for something other than a word or a lemma -> reset + if (!(calculateFor == CalculateFor.WORD || calculateFor == CalculateFor.LEMMA)) { + // if the user selected something else before selecting ngram for letters, reset that choice + calculateFor = CalculateFor.LEMMA; + calculateForRB.selectToggle(lemmaRB); + } + } + + // override if orth mode, allow only word + if (corpus.isGosOrthMode()) { + // TODO change to + varietyRB.setDisable(true); + msdTF.setDisable(true); + } else { + msdTF.setDisable(false); + varietyRB.setDisable(false); + } + } + + private void compute() { + Filter filter = new Filter(); + filter.setNgramValue(0); + filter.setCalculateFor(calculateFor); + filter.setMsd(msd); + filter.setTaxonomy(Tax.getTaxonomyCodes(taxonomy, corpus.getCorpusType())); + filter.setAl(AnalysisLevel.STRING_LEVEL); + filter.setSkipValue(0); + filter.setIsCvv(calculateCvv); + filter.setSolarFilters(solarFiltersMap); + filter.setStringLength(stringLength); + + String message = Validation.validateForStringLevel(filter); + if (message == null) { + // no errors + logger.info("Executing: ", filter.toString()); + StatisticsNew statistic = new StatisticsNew(corpus, filter, useDb); + execute(statistic); + } else { + logAlert(message); + showAlert(Alert.AlertType.ERROR, "Prosim izpolnite polja:", message); + } + } + + private void openHelpWebsite(){ + hostService.showDocument(Messages.HELP_URL); + } + + private void logAlert(String alert) { + logger.info("alert: " + alert); + } + + public Corpus getCorpus() { + return corpus; + } + + public void setCorpus(Corpus corpus) { + this.corpus = corpus; + + if (corpus.getCorpusType() != CorpusType.SOLAR) { + setSelectedFiltersLabel(null); + } else { + setSelectedFiltersLabel("/"); + } + } + + public void setSelectedFiltersLabel(String content) { + if (content != null) { + solarFilters.setVisible(true); + selectedFiltersLabel.setVisible(true); + selectedFiltersLabel.setText(content); + } else { + solarFilters.setVisible(false); + selectedFiltersLabel.setVisible(false); + } + } + + private void execute(StatisticsNew statistic) { + logger.info("Started execution: ", statistic.getFilter()); + + Collection corpusFiles = statistic.getCorpus().getDetectedCorpusFiles(); + boolean corpusIsSplit = corpusFiles.size() > 1; + + final Task task = new Task() { + @SuppressWarnings("Duplicates") + @Override + protected Void call() throws Exception { + long i = 0; + for (File f : corpusFiles) { + readXML(f.toString(), statistic); + i++; + this.updateProgress(i, corpusFiles.size()); + this.updateMessage(String.format(ONGOING_NOTIFICATION_ANALYZING_FILE_X_OF_Y, i, corpusFiles.size(), f.getName())); + } + + return null; + } + }; + + ngramProgressBar.progressProperty().bind(task.progressProperty()); + progressLabel.textProperty().bind(task.messageProperty()); + + task.setOnSucceeded(e -> { + try { + boolean successullySaved = statistic.saveResultToDisk(); + if (successullySaved) { + showAlert(Alert.AlertType.INFORMATION, Messages.NOTIFICATION_ANALYSIS_COMPLETED); + } else { + showAlert(Alert.AlertType.INFORMATION, Messages.NOTIFICATION_ANALYSIS_COMPLETED_NO_RESULTS); + } + } catch (UnsupportedEncodingException e1) { + showAlert(Alert.AlertType.ERROR, ERROR_WHILE_SAVING_RESULTS_TO_CSV); + logger.error("Error while saving", e1); + } + + ngramProgressBar.progressProperty().unbind(); + ngramProgressBar.setStyle(Settings.FX_ACCENT_OK); + progressLabel.textProperty().unbind(); + progressLabel.setText(""); + }); + + task.setOnFailed(e -> { + showAlert(Alert.AlertType.ERROR, ERROR_WHILE_EXECUTING); + logger.error("Error while executing", e); + ngramProgressBar.progressProperty().unbind(); + ngramProgressBar.setProgress(0.0); + ngramProgressBar.setStyle(Settings.FX_ACCENT_NOK); + progressLabel.textProperty().unbind(); + progressLabel.setText(""); + }); + + final Thread thread = new Thread(task, "task"); + thread.setDaemon(true); + thread.start(); + } + + public void setSolarFiltersMap(HashMap> solarFiltersMap) { + this.solarFiltersMap = solarFiltersMap; + } + + public void setHostServices(HostServices hostServices){ + this.hostService = hostServices; + } +} diff --git a/src/main/java/gui/CorpusTab.java b/src/main/java/gui/CorpusTab.java new file mode 100644 index 0000000..48ce9a0 --- /dev/null +++ b/src/main/java/gui/CorpusTab.java @@ -0,0 +1,517 @@ +package gui; + +import static data.CorpusType.*; +import static gui.GUIController.*; +import static gui.Messages.*; +import static util.Util.*; + +import java.io.File; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOCase; +import org.apache.commons.io.filefilter.FileFilterUtils; +import org.apache.commons.io.filefilter.TrueFileFilter; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import alg.XML_processing; +import data.Corpus; +import data.CorpusType; +import data.Enums.solar.SolarFilters; +import data.Tax; +import javafx.collections.ObservableList; +import javafx.concurrent.Task; +import javafx.fxml.FXML; +import javafx.scene.control.*; +import javafx.scene.layout.Pane; +import javafx.stage.DirectoryChooser; +import javafx.stage.Stage; +import javafx.application.HostServices; + +public class CorpusTab { + public final static Logger logger = LogManager.getLogger(CorpusTab.class); + public Pane setCorpusWrapperP; + + private Stage stage; + + @FXML + private Button chooseCorpusLocationB; + private File chosenCorpusLocation; + + @FXML + private CheckBox readHeaderInfoChB; + private boolean readHeaderInfo; + + @FXML + private CheckBox gosUseOrthChB; + private boolean gosUseOrth; + + @FXML + private Button chooseResultsLocationB; + + @FXML + private Label chooseCorpusL; + private String chooseCorpusLabelContent; + + @FXML + private Label chooseResultsL; + private String chooseResultsLabelContent; + + @FXML + private ProgressIndicator locationScanPI; + + @FXML + private Hyperlink helpH; + + // *** shared *** + private Corpus corpus; + private CorpusType corpusType; + + // tabs - used to enable/disable + private Tab stringLevelTabNew2; + private Tab oneWordAnalysisTab; + private Tab characterLevelTab; + private Tab wordFormationTab; + private Tab wordLevelTab; + private Tab filterTab; + private TabPane tabPane; + private StringAnalysisTabNew2 satNew2Controller; + private OneWordAnalysisTab oneWordTabController; + private CharacterAnalysisTab catController; + private FiltersForSolar ffsController; + //private WordFormationTab wfController; + private WordLevelTab wlController; + private HostServices hostService; + + + public void initialize() { + stage = new Stage(); + + // add listeners + chooseCorpusLocationB.setOnAction(e -> chooseCorpusLocation()); + chooseCorpusLocationB.setTooltip(new Tooltip(TOOLTIP_chooseCorpusLocationB)); + helpH.setOnAction(e -> openHelpWebsite()); + + readHeaderInfoChB.selectedProperty().addListener((observable, oldValue, newValue) -> { + readHeaderInfo = newValue; + logger.info("read headers: ", readHeaderInfo); + }); + readHeaderInfoChB.setTooltip(new Tooltip(TOOLTIP_readHeaderInfoChB)); + + gosUseOrthChB.selectedProperty().addListener((observable, oldValue, newValue) -> { + gosUseOrth = newValue; + corpus.setGosOrthMode(gosUseOrth); + wordFormationTab.setDisable(gosUseOrth); + satNew2Controller.toggleMode(null); + oneWordTabController.toggleMode(null); + catController.toggleMode(null); + + logger.info("gosUseOrth: ", gosUseOrth); + }); + + chooseResultsLocationB.setOnAction(e -> chooseResultsLocation(null)); + + // set labels and toggle visibility + toggleGosChBVisibility(); + + chooseCorpusLabelContent = Messages.LABEL_CORPUS_LOCATION_NOT_SET; + chooseCorpusL.setText(chooseCorpusLabelContent); + + chooseResultsLabelContent = Messages.LABEL_RESULTS_LOCATION_NOT_SET; + chooseResultsL.setText(chooseResultsLabelContent); + + togglePiAndSetCorpusWrapper(false); + } + + private void togglePiAndSetCorpusWrapper(boolean piIsActive) { + locationScanPI.setVisible(piIsActive); + setCorpusWrapperP.setLayoutX(piIsActive ? 100.0 : 10.0); + } + + private void openHelpWebsite(){ + hostService.showDocument(Messages.HELP_URL); + } + + /** + * In order for a directory to pass as a valid corpus location, following criteria has to be met: + *
    + *
  • it can't be null
  • + *
  • it has to be readable
  • + *
  • it has to contain xml files
  • + *
  • xml files have to contain valid headers from which we can infer the corpus type
  • + *
  • corpus type must be one of the expected corpus types - as noted in the @see data.CorpusType.class
  • + *
+ *

+ * Additionally, if the user checks to read taxonomy/filters from the corpus files, that read + * has to produce a non-empty list results list + */ + private void chooseCorpusLocation() { + File selectedDirectory = directoryChooser(); + + if (selectedDirectory != null && ValidationUtil.isReadableDirectory(selectedDirectory)) { + logger.info("selected corpus dir: ", selectedDirectory.getAbsolutePath()); + + // scan for xml files + Collection corpusFiles = FileUtils.listFiles(selectedDirectory, FileFilterUtils.suffixFileFilter("xml", IOCase.INSENSITIVE), TrueFileFilter.INSTANCE); + + // make sure there are corpus files in selected directory or notify the user about it + if (corpusFiles.size() == 0) { + logger.info("alert: ", WARNING_CORPUS_NOT_FOUND); + showAlert(Alert.AlertType.ERROR, WARNING_CORPUS_NOT_FOUND, null); + } else { + String chooseCorpusLabelContentTmp = detectCorpusType(corpusFiles, selectedDirectory.getAbsolutePath()); + + if (chooseCorpusLabelContentTmp == null) { + logger.info("alert: ", WARNING_CORPUS_NOT_FOUND); + showAlert(Alert.AlertType.ERROR, WARNING_CORPUS_NOT_FOUND, null); + } else { + initNewCorpus(selectedDirectory, corpusFiles); + + corpus.setChosenCorpusLocation(selectedDirectory); + corpus.setDetectedCorpusFiles(corpusFiles); + chooseCorpusLabelContent = chooseCorpusLabelContentTmp; + logger.info("corpus dir: ", corpus.getChosenCorpusLocation().getAbsolutePath()); + + if (readHeaderInfo) { + logger.info("reading header info..."); + readHeaderInfo(); + } else { + setResults(); + + setCorpusForAnalysis(); + } + } + } + } + } + + /** + * If a user selects a valid corpus location, we define a new corpus (so none of the old data gets carried over) + * + * @param selectedDirectory + * @param corpusFiles + */ + private void initNewCorpus(File selectedDirectory, Collection corpusFiles) { + corpus = new Corpus(); + corpus.setCorpusType(corpusType); + corpus.setDetectedCorpusFiles(corpusFiles); + corpus.setChosenCorpusLocation(selectedDirectory); + chooseResultsLocation(selectedDirectory); + } + + private void chooseResultsLocation(File dir) { + // results location can be set either to default value (after selecting valid corpus location) - dir attribute + // or to a dir picked via directoryChooser (when dir == null + File selectedDirectory = dir == null ? directoryChooser() : dir; + + if (selectedDirectory != null) { + String resultsLocationPath = selectedDirectory.getAbsolutePath().concat(File.separator); + File chosenResultsLocationTmp = new File(resultsLocationPath); + + if (!ValidationUtil.isValidDirectory(chosenResultsLocationTmp)) { + showAlert(Alert.AlertType.ERROR, WARNING_RESULTS_DIR_NOT_VALID); + logger.info("alert: ", WARNING_RESULTS_DIR_NOT_VALID); + } else { + corpus.setChosenResultsLocation(chosenResultsLocationTmp); + chooseResultsLabelContent = corpus.getChosenResultsLocation().getAbsolutePath(); + chooseResultsL.setText(chooseResultsLabelContent); + logger.info("results dir: " + chooseResultsLabelContent); + } + } + } + + private void setResults() { + // if everything is ok + // check and enable checkbox if GOS + toggleGosChBVisibility(); + + // set default results location + String defaultResultsLocationPath = corpus.getChosenCorpusLocation().getAbsolutePath(); + logger.info("setting default results location to: ", defaultResultsLocationPath); + + chooseCorpusL.setText(chooseCorpusLabelContent); + } + + private void readHeaderInfo() { + CorpusType corpusType = corpus.getCorpusType(); + Collection corpusFiles = corpus.getDetectedCorpusFiles(); + togglePiAndSetCorpusWrapper(true); + chooseCorpusL.setText(LABEL_SCANNING_CORPUS); + + logger.info("reading header data for ", corpusType.toString()); + + if (corpusType == CorpusType.GIGAFIDA || corpusType == CorpusType.GOS || corpusType == CorpusType.CCKRES) { + boolean corpusIsSplit = corpusFiles.size() > 1; + + final Task> task = new Task>() { + @Override + protected HashSet call() throws Exception { + HashSet values = new HashSet<>(); + long i = 0; + + if (!corpusIsSplit) { + updateProgress(-1.0f, -1.0f); + } + + for (File file : corpusFiles) { + values.addAll((Collection) XML_processing.readXmlHeaderTaxonomyAndFilters(file.getAbsolutePath(), corpusIsSplit, corpusType)); + i++; + + if (corpusIsSplit) { + updateProgress(i, corpusFiles.size()); + } + } + + updateProgress(1.0f, 1.0f); + return values; + } + }; + + locationScanPI.progressProperty().bind(task.progressProperty()); + + task.setOnSucceeded(e -> { + ObservableList readTaxonomy = Tax.getTaxonomyForComboBox(corpusType, task.getValue()); + + if (ValidationUtil.isEmpty(readTaxonomy)) { + // if no taxonomy found alert the user and keep other tabs disabled + logger.info("No taxonomy found in headers."); + GUIController.showAlert(Alert.AlertType.ERROR, WARNING_NO_TAXONOMY_FOUND); + } else { + // set taxonomy, update label + corpus.setTaxonomy(readTaxonomy); + corpus.setHeaderRead(true); + chooseCorpusL.setText(chooseCorpusLabelContent); + setResults(); + setCorpusForAnalysis(); + } + + togglePiAndSetCorpusWrapper(false); + + }); + + task.setOnCancelled(e -> togglePiAndSetCorpusWrapper(false)); + task.setOnFailed(e -> togglePiAndSetCorpusWrapper(false)); + + final Thread thread = new Thread(task, "task"); + thread.setDaemon(true); + thread.start(); + } else if (corpusType == CorpusType.SOLAR) { + // many many fields + boolean corpusIsSplit = corpusFiles.size() > 1; + + final Task>> task = new Task>>() { + @Override + protected HashMap> call() throws Exception { + HashMap> values = new HashMap<>(); + long i = 0; + + if (!corpusIsSplit) { + updateProgress(-1.0f, -1.0f); + } + + for (File file : corpusFiles) { + HashMap> tmpvalues = (HashMap>) XML_processing.readXmlHeaderTaxonomyAndFilters(file.getAbsolutePath(), corpusIsSplit, corpusType); + + // update final results + for (Map.Entry> entry : tmpvalues.entrySet()) { + if (values.containsKey(entry.getKey())) { + values.get(entry.getKey()).addAll(entry.getValue()); + } else { + values.put(entry.getKey(), entry.getValue()); + } + } + + i++; + + if (corpusIsSplit) { + updateProgress(i, corpusFiles.size()); + } + } + + updateProgress(1.0f, 1.0f); + return values; + } + }; + + locationScanPI.progressProperty().bind(task.progressProperty()); + + task.setOnSucceeded(e -> { + HashMap> values = task.getValue(); + + if (ValidationUtil.isEmpty(values)) { + // if no taxonomy found alert the user and keep other tabs disabled + logger.info("No solar filters found in headers."); + GUIController.showAlert(Alert.AlertType.ERROR, WARNING_NO_SOLAR_FILTERS_FOUND); + } else { + HashMap> filtersForComboBoxes = SolarFilters.getFiltersForComboBoxes(values); + // set taxonomy, update label + corpus.setSolarFiltersForXML(values); + corpus.setSolarFilters(filtersForComboBoxes); + corpus.setHeaderRead(true); + chooseCorpusL.setText(chooseCorpusLabelContent); + setResults(); + setCorpusForAnalysis(); + } + + togglePiAndSetCorpusWrapper(false); + + }); + + task.setOnCancelled(e -> togglePiAndSetCorpusWrapper(false)); + task.setOnFailed(e -> togglePiAndSetCorpusWrapper(false)); + + final Thread thread = new Thread(task, "task"); + thread.setDaemon(true); + thread.start(); + } + + } + + private void setCorpusForAnalysis() { + if (corpus.validate()) { + // new statistic, enable tabs... + stringLevelTabNew2.setDisable(false); + satNew2Controller.setCorpus(corpus); + satNew2Controller.init(); + oneWordAnalysisTab.setDisable(false); + oneWordTabController.setCorpus(corpus); + oneWordTabController.init(); + characterLevelTab.setDisable(false); + catController.setCorpus(corpus); + catController.init(); + wordFormationTab.setDisable(false); + wordLevelTab.setDisable(false); + //wfController.setCorpus(corpus); + //wfController.init(); + wlController.setCorpus(corpus); + wlController.init(); + + if (corpus.getCorpusType() == CorpusType.SOLAR) { + filterTab.setDisable(false); + tabPane.getTabs().add(1, filterTab); + ffsController.setCorpus(corpus); + ffsController.initFilters(); + } else { + filterTab.setDisable(true); + tabPane.getTabs().removeAll(filterTab); + } + } else { + GUIController.showAlert(Alert.AlertType.ERROR, corpus.getValidationErrorsToString()); + } + } + + private File directoryChooser() { + DirectoryChooser directoryChooser = new DirectoryChooser(); + + // open in the folder where the jar is located if possible + File workingDir = getWorkingDirectory(); + + if (workingDir != null) { + directoryChooser.setInitialDirectory(workingDir); + } + + return directoryChooser.showDialog(stage); + } + + /** + * Hides GOS related checkbox until needed. + */ + private void toggleGosChBVisibility() { + gosUseOrthChB.setVisible(corpus != null && corpus.getCorpusType() != null && corpus.getCorpusType() == CorpusType.GOS); + } + + private String detectCorpusType(Collection corpusFiles, String corpusLocation) { + // check that we recognize this corpus + // read first file only, maybe later do all, if toll on resources is acceptable + File f = corpusFiles.iterator().next(); + String title = XML_processing.readXMLHeaderTag(f.getAbsolutePath(), "title").toLowerCase(); + String test = CCKRES.getNameLowerCase(); + String debug = ""; + + // check if XML file's title contains any of recognized corpus titles + corpusType = null; + if (title.contains(SOLAR.getNameLowerCase())) { + corpusType = SOLAR; + } else if (title.contains(GIGAFIDA.getNameLowerCase())) { + corpusType = GIGAFIDA; + } else if (title.contains(CCKRES.getNameLowerCase())) { + corpusType = CCKRES; + } else if (title.contains(GOS.getNameLowerCase())) { + corpusType = GOS; + } + + if (corpusType == null) { + return null; + } else { + corpus.setCorpusType(corpusType); + + StringBuilder sb = new StringBuilder(); + sb.append(corpusLocation) + .append("\n") + .append(String.format(NOTIFICATION_FOUND_X_FILES, corpusFiles.size())) + .append("\n") + .append(String.format("Korpus: %s", corpusType.toString())); + + String result = sb.toString(); + + logger.debug(result); + return result; + } + } + + public Corpus getCorpus() { + return corpus; + } + + public void setCorpus(Corpus corpus) { + this.corpus = corpus; + } + + public void setStringLevelTabNew2(Tab stringLevelTabNew2) { this.stringLevelTabNew2 = stringLevelTabNew2; } + + public void setOneWordAnalysisTab(Tab oneWordAnalysisTab) { this.oneWordAnalysisTab = oneWordAnalysisTab; } + + public void setCharacterLevelTab(Tab characterLevelTab) { this.characterLevelTab = characterLevelTab; } + + public void setWordLevelTab(Tab wordLevelTab) { + this.wordLevelTab = wordLevelTab; + } + + public void setFilterTab(Tab filterTab) { + this.filterTab = filterTab; + } + + public void setFfsController(FiltersForSolar ffsController) { + this.ffsController = ffsController; + } + + public void setTabPane(TabPane tabPane) { + this.tabPane = tabPane; + } + + public void setSatNew2Controller(StringAnalysisTabNew2 satNew2Controller) { this.satNew2Controller = satNew2Controller; } + + public void setOneWordTabController(OneWordAnalysisTab oneWordTabController) { this.oneWordTabController = oneWordTabController; } + + public void setCatController(CharacterAnalysisTab catController) { this.catController = catController; } + + /*public void setWfController(WordFormationTab wfController) { + this.wfController = wfController; + }*/ + + public void setWlController(WordLevelTab wlController) { + this.wlController = wlController; + } + + public void setWordFormationTab(Tab wordFormationTab) { + this.wordFormationTab = wordFormationTab; + } + + public void setHostServices(HostServices hostServices){ + this.hostService = hostServices; + } +} diff --git a/src/main/java/gui/FiltersForSolar.java b/src/main/java/gui/FiltersForSolar.java new file mode 100644 index 0000000..5b59670 --- /dev/null +++ b/src/main/java/gui/FiltersForSolar.java @@ -0,0 +1,187 @@ +package gui; + +import static data.Enums.solar.SolarFilters.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import javafx.application.HostServices; +import javafx.scene.control.Hyperlink; +import org.controlsfx.control.CheckComboBox; + +import data.Corpus; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.layout.AnchorPane; +import util.Util; + +public class FiltersForSolar { + + @FXML + public AnchorPane solarFiltersTabPane; + @FXML + public CheckComboBox solarRegijaCCB; + @FXML + public CheckComboBox solarPredmetCCB; + @FXML + public CheckComboBox solarRazredCCB; + @FXML + public CheckComboBox solarLetoCCB; + @FXML + public CheckComboBox solarSolaCCB; + @FXML + public CheckComboBox solarVrstaBesedilaCCB; + @FXML + public Label selectedFiltersLabel; + @FXML + private Hyperlink helpH; + + private HashMap> selectedFilters; + private Corpus corpus; + + private StringAnalysisTabNew2 satNew2Controller; + private OneWordAnalysisTab oneWordTabController; + private CharacterAnalysisTab catController; + //private WordFormationTab wfController; + private WordLevelTab wlController; + private HostServices hostService; + + @SuppressWarnings("unchecked") + public void initialize() { + selectedFilters = new HashMap<>(); + + solarRegijaCCB.getCheckModel().getCheckedItems().addListener((ListChangeListener) c -> { + selectedFilters.put(REGIJA, solarRegijaCCB.getCheckModel().getCheckedItems()); + updateSolarFilterLabel(); + }); + + solarPredmetCCB.getCheckModel().getCheckedItems().addListener((ListChangeListener) c -> { + selectedFilters.put(PREDMET, solarPredmetCCB.getCheckModel().getCheckedItems()); + updateSolarFilterLabel(); + }); + + solarRazredCCB.getCheckModel().getCheckedItems().addListener((ListChangeListener) c -> { + selectedFilters.put(RAZRED, solarRazredCCB.getCheckModel().getCheckedItems()); + updateSolarFilterLabel(); + }); + + solarLetoCCB.getCheckModel().getCheckedItems().addListener((ListChangeListener) c -> { + selectedFilters.put(LETO, solarLetoCCB.getCheckModel().getCheckedItems()); + updateSolarFilterLabel(); + }); + + solarSolaCCB.getCheckModel().getCheckedItems().addListener((ListChangeListener) c -> { + selectedFilters.put(SOLA, solarSolaCCB.getCheckModel().getCheckedItems()); + updateSolarFilterLabel(); + }); + + solarVrstaBesedilaCCB.getCheckModel().getCheckedItems().addListener((ListChangeListener) c -> { + selectedFilters.put(TIP, solarVrstaBesedilaCCB.getCheckModel().getCheckedItems()); + updateSolarFilterLabel(); + }); + + helpH.setOnAction(e -> openHelpWebsite()); + } + + public void initFilters() { + solarRegijaCCB.getItems().removeAll(); + solarRegijaCCB.getItems().setAll(corpus.getSolarFilters().get(REGIJA)); + solarRegijaCCB.getItems().sorted(); + solarPredmetCCB.getItems().removeAll(); + solarPredmetCCB.getItems().setAll(corpus.getSolarFilters().get(PREDMET)); + solarPredmetCCB.getItems().sorted(); + solarRazredCCB.getItems().removeAll(); + solarRazredCCB.getItems().setAll(corpus.getSolarFilters().get(RAZRED)); + solarRazredCCB.getItems().sorted(); + solarLetoCCB.getItems().removeAll(); + solarLetoCCB.getItems().setAll(corpus.getSolarFilters().get(LETO)); + solarLetoCCB.getItems().sorted(); + solarSolaCCB.getItems().removeAll(); + solarSolaCCB.getItems().setAll(corpus.getSolarFilters().get(SOLA)); + solarSolaCCB.getItems().sorted(); + solarVrstaBesedilaCCB.getItems().removeAll(); + solarVrstaBesedilaCCB.getItems().setAll(corpus.getSolarFilters().get(TIP)); + solarVrstaBesedilaCCB.getItems().sorted(); + } + + private void updateSolarFilterLabel() { + if (Util.isMapEmpty(selectedFilters)) { + setSOlarFIlterLabelText("/"); + } else { + StringBuilder allFilters = new StringBuilder(); + for (Map.Entry> entry : selectedFilters.entrySet()) { + ArrayList values = new ArrayList<>(entry.getValue()); + + if (!values.isEmpty()) { + allFilters.append(entry.getKey()) + .append(": "); + + for (int i = 0; i < values.size(); i++) { + allFilters.append(values.get(i)); + + if (i < values.size() - 1) { + // so we won't append a comma after the last element + allFilters.append(", "); + } + } + allFilters.append("\n\n"); + } + } + + setSOlarFIlterLabelText(allFilters.toString()); + } + + HashMap> solarFiltersMap = new HashMap<>(); + for (Map.Entry> e : selectedFilters.entrySet()) { + HashSet values = new HashSet<>(); + values.addAll(e.getValue()); + + solarFiltersMap.put(e.getKey(), values); + } + + satNew2Controller.setSolarFiltersMap(solarFiltersMap); + oneWordTabController.setSolarFiltersMap(solarFiltersMap); + catController.setSolarFiltersMap(solarFiltersMap); + //wfController.setSolarFiltersMap(solarFiltersMap); + wlController.setSolarFiltersMap(solarFiltersMap); + } + + private void openHelpWebsite(){ + hostService.showDocument(Messages.HELP_URL); + } + + private void setSOlarFIlterLabelText(String content) { + selectedFiltersLabel.setText(content); + satNew2Controller.setSelectedFiltersLabel(content); + oneWordTabController.setSelectedFiltersLabel(content); + catController.setSelectedFiltersLabel(content); + //wfController.setSelectedFiltersLabel(content); + wlController.setSelectedFiltersLabel(content); + } + + public void setCorpus(Corpus corpus) { + this.corpus = corpus; + } + + public void setSatNew2Controller(StringAnalysisTabNew2 satNew2Controller) { this.satNew2Controller = satNew2Controller; } + + public void setOneWordTabController(OneWordAnalysisTab oneWordTabController) { this.oneWordTabController = oneWordTabController; } + + public void setCatController(CharacterAnalysisTab catController) { this.catController = catController; } + + /*public void setWfController(WordFormationTab wfController) { + this.wfController = wfController; + }*/ + + public void setWlController(WordLevelTab wlController) { + this.wlController = wlController; + } + + public void setHostServices(HostServices hostServices){ + this.hostService = hostServices; + } +} diff --git a/src/main/java/gui/GUIController.java b/src/main/java/gui/GUIController.java new file mode 100644 index 0000000..4bd6a33 --- /dev/null +++ b/src/main/java/gui/GUIController.java @@ -0,0 +1,150 @@ +package gui; + +import java.io.IOException; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.kordamp.ikonli.fontawesome.FontAwesome; +import org.kordamp.ikonli.javafx.FontIcon; + +import data.Corpus; +import javafx.application.Application; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import javafx.stage.Stage; + +public class GUIController extends Application { + public final static Logger logger = LogManager.getLogger(GUIController.class); + + @FXML + public Tab StringLevelTabNew2; + @FXML + public Tab OneWordAnalysisTab; + @FXML + public Tab CharacterLevelTabNew; + @FXML + public Tab corpusTab; + public TabPane tabPane; + @FXML + private CharacterAnalysisTab catController; + @FXML + private static Parent sat; + @FXML + private StringAnalysisTabNew2 satNew2Controller; + @FXML + private static Parent satNew2; + @FXML + private OneWordAnalysisTab oneWordTabController; + @FXML + private static Parent oneWordTab; + @FXML + private CorpusTab ctController; + @FXML + private Parent ct; + //@FXML + //private WordFormationTab wfController; + @FXML + private Parent wf; + @FXML + private WordLevelTab wlController; + @FXML + private Parent wl; + @FXML + private FiltersForSolar ffsController; + @FXML + private Parent ffs; + @FXML + private SelectedFiltersPane sfpController; + @FXML + private Parent sfp; + @FXML + public Tab stringLevelTab; + @FXML + public Tab wordLevelTab; + /*@FXML + public Tab wordFormationTab;*/ + + + @FXML + public Tab filterTab; + public Stage stage; + + private Corpus corpus; + + + @Override + public void start(Stage primaryStage) throws IOException { + Parent root = FXMLLoader.load(getClass().getResource("/GUI.fxml")); + primaryStage.setTitle("GUI"); + Scene scene = new Scene(root, 800, 600); + // https://github.com/dicolar/jbootx + // scene.getStylesheets().add(GUIController.class.getResource("bootstrap3.css").toExternalForm()) + primaryStage.setScene(scene); + stage = primaryStage; + primaryStage.show(); + } + + public static void main(String[] args) { + launch(args); + } + + public void initialize() { + corpus = new Corpus(); + ctController.setCorpus(corpus); + ctController.setFilterTab(filterTab); + ctController.setStringLevelTabNew2(StringLevelTabNew2); + ctController.setOneWordAnalysisTab(OneWordAnalysisTab); + ctController.setCharacterLevelTab(CharacterLevelTabNew); + ctController.setSatNew2Controller(satNew2Controller); + ctController.setOneWordTabController(oneWordTabController); + ctController.setCatController(catController); + //ctController.setWfController(wfController); + ctController.setWlController(wlController); + ctController.setTabPane(tabPane); + ctController.setFfsController(ffsController); + //ctController.setWordFormationTab(wordFormationTab); + ctController.setWordLevelTab(wordLevelTab); + ctController.setHostServices(getHostServices()); + + satNew2Controller.setCorpus(corpus); + satNew2Controller.setHostServices(getHostServices()); + oneWordTabController.setCorpus(corpus); + oneWordTabController.setHostServices(getHostServices()); + catController.setCorpus(corpus); + catController.setHostServices(getHostServices()); + //wfController.setCorpus(corpus); + //wfController.setHostServices(getHostServices()); + wlController.setCorpus(corpus); + wlController.setHostServices(getHostServices()); + ffsController.setSatNew2Controller(satNew2Controller); + ffsController.setOneWordTabController(oneWordTabController); + ffsController.setCatController(catController); + //ffsController.setWfController(wfController); + ffsController.setWlController(wlController); + ffsController.setHostServices(getHostServices()); + + // set tab icons + corpusTab.setGraphic(new FontIcon(FontAwesome.COG)); + filterTab.setGraphic(new FontIcon(FontAwesome.FILTER)); + + // hide filter tab + tabPane.getTabs().removeAll(filterTab); + } + + static void showAlert(Alert.AlertType alertType, String headerText, String contentText) { + Alert alert = new Alert(alertType); + alert.setTitle(Messages.windowTitles.get(alertType)); + alert.setHeaderText(headerText != null ? headerText : ""); + alert.setContentText(contentText != null ? contentText : ""); + alert.showAndWait(); + } + + static void showAlert(Alert.AlertType alertType, String headerText) { + showAlert(alertType, headerText, null); + } +} \ No newline at end of file diff --git a/src/main/java/gui/Messages.java b/src/main/java/gui/Messages.java new file mode 100644 index 0000000..f26d937 --- /dev/null +++ b/src/main/java/gui/Messages.java @@ -0,0 +1,74 @@ +package gui; + +import static javafx.scene.control.Alert.AlertType.*; + +import java.util.HashMap; + +import javafx.scene.control.Alert; + +public class Messages { + + // warnings & errors + public static final String WARNING_CORPUS_NOT_FOUND = "V izbranem direktoriju ni ustreznih korpusnih datotek."; + public static final String WARNING_RESULTS_DIR_NOT_VALID = "Za dostop do izbranega direktorija nimate potrebnih pravic."; + public static final String WARNING_DIFFERING_NGRAM_LEVEL_AND_FILTER_TOKENS = "Izbran nivo ngramov in vpisano št. besed v filtru se ne ujemata."; + public static final String WARNING_DIFFERING_NGRAM_LEVEL_AND_FILTER_TOKENS_INFO = "Izberite drugo število ali popravite filter."; + public static final String WARNING_WORD_OR_LEMMA = "Izberite, če želite statistiko izračunati za besede ali leme."; + public static final String WARNING_ONLY_NUMBERS_ALLOWED = "Prosim vnesite veljavno število."; + public static final String WARNING_MISMATCHED_NGRAM_AND_TOKENS_VALUES = "Število za ngram (%d) in število msd oznak (%d) se morata ujemati."; + public static final String WARNING_MISSING_STRING_LENGTH = "Dolžina niza mora biti večja od 0. Vstavljena je privzeta vrednost (1)."; + public static final String WARNING_NO_TAXONOMY_FOUND = "Iz korpusnih datotek ni bilo moč razbrati taksonomije. Prosim izberite drugo lokacijo ali korpus."; + public static final String WARNING_NO_SOLAR_FILTERS_FOUND = "Iz korpusnih datotek ni bilo moč razbrati filtrov. Prosim izberite drugo lokacijo ali korpus."; + public static final String ERROR_WHILE_EXECUTING = "Prišlo je do napake med izvajanjem."; + public static final String ERROR_WHILE_SAVING_RESULTS_TO_CSV = "Prišlo je do napake med shranjevanje rezultatov."; + + // missing + public static final String MISSING_NGRAM_LEVEL = "N-gram nivo"; + public static final String MISSING_CALCULATE_FOR = "Izračunaj za"; + public static final String MISSING_SKIP = ""; + public static final String MISSING_STRING_LENGTH = "Dolžina niza"; + public static final String MISMATCHED_STRING_LENGTH_AND_MSD_REGEX = "Neujemajoča dolžina niza in regex filter"; + + + // general notifications - static content/set only once + public static final String NOTIFICATION_FOUND_X_FILES = "Št. najdenih datotek: %d"; + public static final String NOTIFICATION_ANALYSIS_COMPLETED = "Analiza je zaključena, rezultati so shranjeni."; + public static final String NOTIFICATION_ANALYSIS_COMPLETED_NO_RESULTS = "Analiza je zaključena, vendar ni bilo moč izračunati statistike, ki bi ustrezala vsem navedenim pogojem."; + public static final String RESULTS_PATH_SET_TO_DEFAULT = "Lokacija za shranjevanje rezultatov je nastavljena na lokacijo korpusa."; + + // ongoing notifications - displayed while processing, dynamically changing + public static final String ONGOING_NOTIFICATION_ANALYZING_FILE_X_OF_Y = "Analiziram datoteko %d od %d (%s)"; + + // Labels + public static final String LABEL_CORPUS_LOCATION_NOT_SET = "Lokacija korpusa ni nastavljena"; + public static final String LABEL_RESULTS_LOCATION_NOT_SET = "Lokacija za shranjevanje rezultatov ni nastavljena"; + public static final String LABEL_RESULTS_CORPUS_TYPE_NOT_SET = "Vrsta korpusa ni nastavljena"; + + public static final String LABEL_SCANNING_CORPUS = "Iskanje in analiza korpusnih datotek..."; + public static final String LABEL_SCANNING_SINGLE_FILE_CORPUS = "Analiza vnosa "; + public static final String COMPLETED = "končano"; + + public static final String TOOLTIP_chooseCorpusLocationB = "Izberite mapo v kateri se nahaja korpus. Program izbrano mapo preišče rekurzivno, zato bodite pozorni, da ne izberete mape z več korpusi ali z mnogo datotekami, ki niso del korpusa."; + public static final String TOOLTIP_readHeaderInfoChB = "Če izberete to opcijo, se bo iz headerjev korpusa prebrala razpoložljiva taksonomija oz. filtri (korpus Šolar). Ta operacija lahko traja dlje časa, sploh če je korpus združen v eni sami datoteki."; + + + + // Not properly to be here. TODO move somewhere else in future + public static final String HELP_URL = "http://slovnica.ijs.si/"; + + // helper maps + /** + * Typical window titles + * ERROR = "Napaka" + * WARNING = "Opozorilo" + * CONFIRMATION = "Potrdilo" + */ + static HashMap windowTitles = new HashMap<>(); + + static { + // automatically set window's title + windowTitles.put(ERROR, "Napaka"); + windowTitles.put(WARNING, "Opozorilo"); + windowTitles.put(CONFIRMATION, "Potrdilo"); + } +} diff --git a/src/main/java/gui/OneWordAnalysisTab.java b/src/main/java/gui/OneWordAnalysisTab.java new file mode 100755 index 0000000..44c3e79 --- /dev/null +++ b/src/main/java/gui/OneWordAnalysisTab.java @@ -0,0 +1,389 @@ +package gui; + +import data.*; +import javafx.application.HostServices; +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.concurrent.Task; +import javafx.fxml.FXML; +import javafx.scene.control.*; +import javafx.scene.layout.Pane; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.controlsfx.control.CheckComboBox; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.util.*; +import java.util.regex.Pattern; + +import static alg.XML_processing.readXML; +import static gui.GUIController.showAlert; +import static gui.Messages.*; + +@SuppressWarnings("Duplicates") +public class OneWordAnalysisTab { + public final static Logger logger = LogManager.getLogger(OneWordAnalysisTab.class); + + @FXML + public Label selectedFiltersLabel; + @FXML + public Label solarFilters; + + @FXML + private TextField msdTF; + private ArrayList msd; + private ArrayList msdStrings; + + @FXML + private CheckComboBox taxonomyCCB; + private ArrayList taxonomy; + + @FXML + private ComboBox calculateForCB; + private CalculateFor calculateFor; + + + @FXML + private Button computeNgramsB; + + @FXML + public ProgressBar ngramProgressBar; + @FXML + public Label progressLabel; + + @FXML + private Hyperlink helpH; + + private enum MODE { + LETTER, + WORD + } + + private MODE currentMode; + + private Corpus corpus; + private HashMap> solarFiltersMap; + private Filter filter; + private boolean useDb; + private HostServices hostService; + + private static final ObservableList N_GRAM_COMPUTE_FOR_WORDS = FXCollections.observableArrayList("lema", "različnica", "oblikoskladenjska oznaka"); + private static final ObservableList N_GRAM_COMPUTE_FOR_LETTERS = FXCollections.observableArrayList("lema", "različnica"); + private static final ObservableList N_GRAM_COMPUTE_FOR_WORDS_ORTH = FXCollections.observableArrayList("različnica"); + + + // TODO: pass observables for taxonomy based on header scan + // after header scan + private ObservableList taxonomyCCBValues; + private CorpusType currentCorpusType; + + public void init() { + currentMode = MODE.WORD; + toggleMode(currentMode); + + // calculateForCB + calculateForCB.valueProperty().addListener((observable, oldValue, newValue) -> { + calculateFor = CalculateFor.factory(newValue); + logger.info("calculateForCB:", calculateFor.toString()); + }); + + calculateForCB.getSelectionModel().select(0); + + // msd + msdTF.focusedProperty().addListener((observable, oldValue, newValue) -> { + if (!newValue) { + // focus lost + String value = msdTF.getText(); + logger.info("msdTf: ", value); + + if (!ValidationUtil.isEmpty(value)) { + ArrayList msdTmp = new ArrayList<>(Arrays.asList(value.split(" "))); + + int nOfRequiredMsdTokens = 1; + if (msdTmp.size() != nOfRequiredMsdTokens) { + String msg = String.format(Messages.WARNING_MISMATCHED_NGRAM_AND_TOKENS_VALUES, nOfRequiredMsdTokens, msdTmp.size()); + logAlert(msg); + showAlert(Alert.AlertType.ERROR, msg); + } + msd = new ArrayList<>(); + msdStrings = new ArrayList<>(); + for (String msdToken : msdTmp) { + msd.add(Pattern.compile(msdToken)); + msdStrings.add(msdToken); + } + logger.info(String.format("msd accepted (%d)", msd.size())); + + } else if (!ValidationUtil.isEmpty(newValue)) { + msd = new ArrayList<>(); + msdStrings = new ArrayList<>(); + } + } + }); + + msdTF.setText(""); + msd = new ArrayList<>(); + + // taxonomy + if (Tax.getCorpusTypesWithTaxonomy().contains(corpus.getCorpusType())) { + taxonomyCCB.getItems().removeAll(); + taxonomyCCB.getItems().setAll(corpus.getTaxonomy()); + taxonomyCCB.getCheckModel().getCheckedItems().addListener((ListChangeListener) c -> { + taxonomy = new ArrayList<>(); + ObservableList checkedItems = taxonomyCCB.getCheckModel().getCheckedItems(); + taxonomy.addAll(checkedItems); + logger.info(String.format("Selected taxonomy: %s", StringUtils.join(checkedItems, ","))); + }); + taxonomyCCB.getCheckModel().clearChecks(); + } else { + taxonomyCCB.setDisable(true); + } + + computeNgramsB.setOnAction(e -> { + compute(); + logger.info("compute button"); + }); + helpH.setOnAction(e -> openHelpWebsite()); + } + + /** + * case a: values for combo boxes can change after a corpus change + *

    + *
  • different corpus type - reset all fields so no old values remain
  • + *
  • same corpus type, different subset - keep
  • + *
+ *

+ * case b: values for combo boxes can change after a header scan + *

    + *
  • at first, fields are populated by corpus type defaults
  • + *
  • after, with gathered data
  • + *
+ *

+ * ngrams: 1 + * calculateFor: word + * msd: + * taxonomy: + * skip: 0 + * iscvv: false + * string length: 1 + */ + public void populateFields() { + // corpus changed if: current one is null (this is first run of the app) + // or if currentCorpus != gui's corpus + boolean corpusChanged = currentCorpusType == null + || currentCorpusType != corpus.getCorpusType(); + + + // TODO: check for GOS, GIGAFIDA, SOLAR... + // refresh and: + // TODO if current value != null && is in new calculateFor ? keep : otherwise reset + if (calculateFor == null) { + calculateForCB.getSelectionModel().select(calculateForCB.getItems().get(0)); + calculateFor = CalculateFor.factory(calculateForCB.getItems().get(0)); + } + + if (!filter.hasMsd()) { + // if current corpus doesn't have msd data, disable this field + msd = new ArrayList<>(); + msdTF.setText(""); + msdTF.setDisable(true); + logger.info("no msd data"); + } else { + if (ValidationUtil.isEmpty(msd) + || (!ValidationUtil.isEmpty(msd) && corpusChanged)) { + // msd has not been set previously + // or msd has been set but the corpus changed -> reset + msd = new ArrayList<>(); + msdTF.setText(""); + msdTF.setDisable(false); + logger.info("msd reset"); + } else if (!ValidationUtil.isEmpty(msd) && !corpusChanged) { + // if msd has been set, but corpus type remained the same, we can keep any set msd value + msdTF.setText(StringUtils.join(msdStrings, " ")); + msdTF.setDisable(false); + logger.info("msd kept"); + } + } + + // TODO: trigger on rescan + if ((currentCorpusType != null && currentCorpusType != corpus.getCorpusType())) { + // user changed corpus (by type) or by selection & triggered a rescan of headers + // see if we read taxonomy from headers, otherwise use default values for given corpus + ObservableList tax = corpus.getTaxonomy(); + taxonomyCCBValues = tax != null ? tax : Taxonomy.getDefaultForComboBox(corpus.getCorpusType()); + + currentCorpusType = corpus.getCorpusType(); + // setTaxonomyIsDirty(false); + } else { + + } + + // see if we read taxonomy from headers, otherwise use default values for given corpus + ObservableList tax = corpus.getTaxonomy(); + taxonomyCCBValues = tax != null ? tax : Taxonomy.getDefaultForComboBox(corpus.getCorpusType()); + taxonomyCCB.getItems().addAll(taxonomyCCBValues); + + } + + /** + * Toggles visibility for panes which hold fields for skipgram value (not applicable when calculating for letters) etc., + * sets combobox values to what is applicable ... + * + * @param mode + */ + public void toggleMode(MODE mode) { + if (mode == null) { + mode = currentMode; + } + + logger.info("mode: ", mode.toString()); + + if (mode == MODE.WORD) { + calculateForCB.getItems().setAll(N_GRAM_COMPUTE_FOR_WORDS); + } else if (mode == MODE.LETTER) { + calculateForCB.getItems().setAll(N_GRAM_COMPUTE_FOR_LETTERS); + + + // if calculateFor was selected for something other than a word or a lemma -> reset + if (!(calculateFor == CalculateFor.WORD || calculateFor == CalculateFor.LEMMA)) { + // if the user selected something else before selecting ngram for letters, reset that choice + calculateFor = CalculateFor.WORD; + calculateForCB.getSelectionModel().select("različnica"); + } + } + + // override if orth mode, allow only word + if (corpus.isGosOrthMode()) { + calculateForCB.getItems().setAll(N_GRAM_COMPUTE_FOR_WORDS_ORTH); + msdTF.setDisable(true); + } else { + msdTF.setDisable(false); + } + } + + private void compute() { + Filter filter = new Filter(); + filter.setNgramValue(1); + filter.setCalculateFor(calculateFor); + filter.setMsd(msd); + filter.setTaxonomy(Tax.getTaxonomyCodes(taxonomy, corpus.getCorpusType())); + filter.setAl(AnalysisLevel.STRING_LEVEL); + filter.setSkipValue(0); + filter.setIsCvv(false); + filter.setSolarFilters(solarFiltersMap); + filter.setStringLength(1); + + String message = Validation.validateForStringLevel(filter); + if (message == null) { + // no errors + logger.info("Executing: ", filter.toString()); + StatisticsNew statistic = new StatisticsNew(corpus, filter, useDb); + execute(statistic); + } else { + logAlert(message); + showAlert(Alert.AlertType.ERROR, "Prosim izpolnite polja:", message); + } + } + + private void logAlert(String alert) { + logger.info("alert: " + alert); + } + + private void openHelpWebsite(){ + hostService.showDocument(Messages.HELP_URL); + } + + public Corpus getCorpus() { + return corpus; + } + + public void setCorpus(Corpus corpus) { + this.corpus = corpus; + + if (corpus.getCorpusType() != CorpusType.SOLAR) { + setSelectedFiltersLabel(null); + } else { + setSelectedFiltersLabel("/"); + } + } + + public void setSelectedFiltersLabel(String content) { + if (content != null) { + solarFilters.setVisible(true); + selectedFiltersLabel.setVisible(true); + selectedFiltersLabel.setText(content); + } else { + solarFilters.setVisible(false); + selectedFiltersLabel.setVisible(false); + } + } + + private void execute(StatisticsNew statistic) { + logger.info("Started execution: ", statistic.getFilter()); + + Collection corpusFiles = statistic.getCorpus().getDetectedCorpusFiles(); + boolean corpusIsSplit = corpusFiles.size() > 1; + + final Task task = new Task() { + @SuppressWarnings("Duplicates") + @Override + protected Void call() throws Exception { + long i = 0; + for (File f : corpusFiles) { + readXML(f.toString(), statistic); + i++; + this.updateProgress(i, corpusFiles.size()); + this.updateMessage(String.format(ONGOING_NOTIFICATION_ANALYZING_FILE_X_OF_Y, i, corpusFiles.size(), f.getName())); + } + + return null; + } + }; + + ngramProgressBar.progressProperty().bind(task.progressProperty()); + progressLabel.textProperty().bind(task.messageProperty()); + + task.setOnSucceeded(e -> { + try { + boolean successullySaved = statistic.saveResultToDisk(); + if (successullySaved) { + showAlert(Alert.AlertType.INFORMATION, Messages.NOTIFICATION_ANALYSIS_COMPLETED); + } else { + showAlert(Alert.AlertType.INFORMATION, Messages.NOTIFICATION_ANALYSIS_COMPLETED_NO_RESULTS); + } + } catch (UnsupportedEncodingException e1) { + showAlert(Alert.AlertType.ERROR, ERROR_WHILE_SAVING_RESULTS_TO_CSV); + logger.error("Error while saving", e1); + } + + ngramProgressBar.progressProperty().unbind(); + ngramProgressBar.setStyle(Settings.FX_ACCENT_OK); + progressLabel.textProperty().unbind(); + progressLabel.setText(""); + }); + + task.setOnFailed(e -> { + showAlert(Alert.AlertType.ERROR, ERROR_WHILE_EXECUTING); + logger.error("Error while executing", e); + ngramProgressBar.progressProperty().unbind(); + ngramProgressBar.setProgress(0.0); + ngramProgressBar.setStyle(Settings.FX_ACCENT_NOK); + progressLabel.textProperty().unbind(); + progressLabel.setText(""); + }); + + final Thread thread = new Thread(task, "task"); + thread.setDaemon(true); + thread.start(); + } + + public void setSolarFiltersMap(HashMap> solarFiltersMap) { + this.solarFiltersMap = solarFiltersMap; + } + public void setHostServices(HostServices hostServices){ + this.hostService = hostServices; + } + +} diff --git a/src/main/java/gui/SelectedFiltersPane.java b/src/main/java/gui/SelectedFiltersPane.java new file mode 100644 index 0000000..765a8ef --- /dev/null +++ b/src/main/java/gui/SelectedFiltersPane.java @@ -0,0 +1,18 @@ +package gui; + +import javafx.scene.control.Label; + +public class SelectedFiltersPane { + + + public Label selectedFiltersLabel; + + public Label getSelectedFiltersLabel() { + return selectedFiltersLabel; + } + + public void setSelectedFiltersLabel(String filters) { + this.selectedFiltersLabel = new Label(filters); + this.selectedFiltersLabel.setText("test?"); + } +} diff --git a/src/main/java/gui/StringAnalysisTabNew2.java b/src/main/java/gui/StringAnalysisTabNew2.java new file mode 100755 index 0000000..1db9293 --- /dev/null +++ b/src/main/java/gui/StringAnalysisTabNew2.java @@ -0,0 +1,511 @@ +package gui; + +import static alg.XML_processing.*; +import static gui.GUIController.*; +import static gui.Messages.*; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.util.*; +import java.util.regex.Pattern; + +import javafx.application.HostServices; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.controlsfx.control.CheckComboBox; + +import data.*; +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.concurrent.Task; +import javafx.fxml.FXML; +import javafx.scene.control.*; +import javafx.scene.layout.Pane; + +@SuppressWarnings("Duplicates") +public class StringAnalysisTabNew2 { + public final static Logger logger = LogManager.getLogger(StringAnalysisTabNew2.class); + + @FXML + public Label selectedFiltersLabel; + @FXML + public Label solarFilters; + + @FXML + private TextField msdTF; + private ArrayList msd; + private ArrayList msdStrings; + + @FXML + private CheckComboBox taxonomyCCB; + private ArrayList taxonomy; + + @FXML + private CheckBox calculatecvvCB; + private boolean calculateCvv; + + @FXML + private TextField stringLengthTF; + private Integer stringLength; + + @FXML + private ComboBox calculateForCB; + private CalculateFor calculateFor; + + @FXML + private ComboBox ngramValueCB; + private Integer ngramValue; + + @FXML + private ComboBox skipValueCB; + private Integer skipValue; + + @FXML + private Pane paneWords; + + @FXML + private Pane paneLetters; + + @FXML + private Button computeNgramsB; + + @FXML + public ProgressBar ngramProgressBar; + @FXML + public Label progressLabel; + + @FXML + private Hyperlink helpH; + + private enum MODE { + LETTER, + WORD + } + + private MODE currentMode; + + private Corpus corpus; + private HashMap> solarFiltersMap; + private Filter filter; + private boolean useDb; + private HostServices hostService; + + private static final ObservableList N_GRAM_COMPUTE_FOR_WORDS = FXCollections.observableArrayList("lema", "različnica", "oblikoskladenjska oznaka"); + private static final ObservableList N_GRAM_COMPUTE_FOR_LETTERS = FXCollections.observableArrayList("lema", "različnica"); + private static final ObservableList N_GRAM_COMPUTE_FOR_WORDS_ORTH = FXCollections.observableArrayList("različnica"); + + + // TODO: pass observables for taxonomy based on header scan + // after header scan + private ObservableList taxonomyCCBValues; + private CorpusType currentCorpusType; + + public void init() { + currentMode = MODE.WORD; + toggleMode(currentMode); + + // ngram value CB + ngramValueCB.valueProperty().addListener((observable, oldValue, newValue) -> { + if (newValue.equals("nivo črk")) { + ngramValue = 0; + toggleMode(MODE.LETTER); + } else { + ngramValue = Integer.valueOf(newValue); + toggleMode(MODE.WORD); + } + + // skip only on ngrams of more than one word + if (ngramValue > 1) { + skipValueCB.setDisable(false); + } else { + skipValueCB.getSelectionModel().select(0); + skipValue = 0; + skipValueCB.setDisable(true); + } + + logger.info("ngramValueCB:", ngramValue); + }); + + // set first n-gram value to 2 at index 0 + ngramValueCB.getSelectionModel().select(0); // selected index + ngramValue = 2; // actual value at that index + + // calculateForCB + calculateForCB.valueProperty().addListener((observable, oldValue, newValue) -> { + calculateFor = CalculateFor.factory(newValue); + logger.info("calculateForCB:", calculateFor.toString()); + }); + + calculateForCB.getSelectionModel().select(0); + + // msd + msdTF.focusedProperty().addListener((observable, oldValue, newValue) -> { + if (!newValue) { + // focus lost + String value = msdTF.getText(); + logger.info("msdTf: ", value); + + if (!ValidationUtil.isEmpty(value)) { + ArrayList msdTmp = new ArrayList<>(Arrays.asList(value.split(" "))); + + int nOfRequiredMsdTokens = ngramValue == 0 ? 1 : ngramValue; + if (msdTmp.size() != nOfRequiredMsdTokens) { + String msg = String.format(Messages.WARNING_MISMATCHED_NGRAM_AND_TOKENS_VALUES, nOfRequiredMsdTokens, msdTmp.size()); + logAlert(msg); + showAlert(Alert.AlertType.ERROR, msg); + } + msd = new ArrayList<>(); + msdStrings = new ArrayList<>(); + for (String msdToken : msdTmp) { + msd.add(Pattern.compile(msdToken)); + msdStrings.add(msdToken); + } + logger.info(String.format("msd accepted (%d)", msd.size())); + + } else if (!ValidationUtil.isEmpty(newValue)) { + msd = new ArrayList<>(); + msdStrings = new ArrayList<>(); + } + } + }); + + msdTF.setText(""); + msd = new ArrayList<>(); + + // taxonomy + if (Tax.getCorpusTypesWithTaxonomy().contains(corpus.getCorpusType())) { + taxonomyCCB.getItems().removeAll(); + taxonomyCCB.getItems().setAll(corpus.getTaxonomy()); + taxonomyCCB.getCheckModel().getCheckedItems().addListener((ListChangeListener) c -> { + taxonomy = new ArrayList<>(); + ObservableList checkedItems = taxonomyCCB.getCheckModel().getCheckedItems(); + taxonomy.addAll(checkedItems); + logger.info(String.format("Selected taxonomy: %s", StringUtils.join(checkedItems, ","))); + }); + taxonomyCCB.getCheckModel().clearChecks(); + } else { + taxonomyCCB.setDisable(true); + } + + // skip + skipValueCB.valueProperty().addListener((observable, oldValue, newValue) -> { + skipValue = Integer.valueOf(newValue); + logger.info("Skip " + skipValue); + }); + + skipValueCB.getSelectionModel().select(0); + skipValue = 0; + + // cvv + calculatecvvCB.selectedProperty().addListener((observable, oldValue, newValue) -> { + calculateCvv = newValue; + logger.info("calculate cvv: " + calculateCvv); + }); + + calculatecvvCB.setSelected(false); + + // string length + stringLengthTF.focusedProperty().addListener((observable, oldValue, newValue) -> { + if (!newValue) { + // focus lost + String value = stringLengthTF.getText(); + if (!ValidationUtil.isEmpty(value)) { + if (!ValidationUtil.isNumber(value)) { + logAlert("stringlengthTf: " + WARNING_ONLY_NUMBERS_ALLOWED); + GUIController.showAlert(Alert.AlertType.ERROR, WARNING_ONLY_NUMBERS_ALLOWED); + } + stringLength = Integer.parseInt(value); + } else { + GUIController.showAlert(Alert.AlertType.ERROR, WARNING_MISSING_STRING_LENGTH); + stringLengthTF.setText("1"); + logAlert(WARNING_MISSING_STRING_LENGTH); + } + } + }); + + computeNgramsB.setOnAction(e -> { + compute(); + logger.info("compute button"); + }); + + helpH.setOnAction(e -> openHelpWebsite()); + } + + /** + * case a: values for combo boxes can change after a corpus change + *
    + *
  • different corpus type - reset all fields so no old values remain
  • + *
  • same corpus type, different subset - keep
  • + *
+ *

+ * case b: values for combo boxes can change after a header scan + *

    + *
  • at first, fields are populated by corpus type defaults
  • + *
  • after, with gathered data
  • + *
+ *

+ * ngrams: 1 + * calculateFor: word + * msd: + * taxonomy: + * skip: 0 + * iscvv: false + * string length: 1 + */ + public void populateFields() { + // corpus changed if: current one is null (this is first run of the app) + // or if currentCorpus != gui's corpus + boolean corpusChanged = currentCorpusType == null + || currentCorpusType != corpus.getCorpusType(); + + // keep ngram value if set + if (ngramValue == null) { + ngramValueCB.getSelectionModel().select("1"); + ngramValue = 1; + } + + // TODO: check for GOS, GIGAFIDA, SOLAR... + // refresh and: + // TODO if current value != null && is in new calculateFor ? keep : otherwise reset + if (calculateFor == null) { + calculateForCB.getSelectionModel().select(calculateForCB.getItems().get(0)); + calculateFor = CalculateFor.factory(calculateForCB.getItems().get(0)); + } + + if (!filter.hasMsd()) { + // if current corpus doesn't have msd data, disable this field + msd = new ArrayList<>(); + msdTF.setText(""); + msdTF.setDisable(true); + logger.info("no msd data"); + } else { + if (ValidationUtil.isEmpty(msd) + || (!ValidationUtil.isEmpty(msd) && corpusChanged)) { + // msd has not been set previously + // or msd has been set but the corpus changed -> reset + msd = new ArrayList<>(); + msdTF.setText(""); + msdTF.setDisable(false); + logger.info("msd reset"); + } else if (!ValidationUtil.isEmpty(msd) && !corpusChanged) { + // if msd has been set, but corpus type remained the same, we can keep any set msd value + msdTF.setText(StringUtils.join(msdStrings, " ")); + msdTF.setDisable(false); + logger.info("msd kept"); + } + } + + // TODO: taxonomy: refresh and keep if in new taxonomy, otherwise empty (no selection) + + // keep skip value + if (skipValue == null) { + skipValueCB.getSelectionModel().select("0"); + skipValue = 0; + } + + // keep calculateCvv + calculatecvvCB.setSelected(calculateCvv); + + // keep string length if set + if (stringLength != null) { + stringLengthTF.setText(String.valueOf(stringLength)); + } else { + stringLengthTF.setText("1"); + stringLength = 1; + } + + // TODO: trigger on rescan + if ((currentCorpusType != null && currentCorpusType != corpus.getCorpusType())) { + // user changed corpus (by type) or by selection & triggered a rescan of headers + // see if we read taxonomy from headers, otherwise use default values for given corpus + ObservableList tax = corpus.getTaxonomy(); + taxonomyCCBValues = tax != null ? tax : Taxonomy.getDefaultForComboBox(corpus.getCorpusType()); + + currentCorpusType = corpus.getCorpusType(); + // setTaxonomyIsDirty(false); + } else { + + } + + // see if we read taxonomy from headers, otherwise use default values for given corpus + ObservableList tax = corpus.getTaxonomy(); + taxonomyCCBValues = tax != null ? tax : Taxonomy.getDefaultForComboBox(corpus.getCorpusType()); + taxonomyCCB.getItems().addAll(taxonomyCCBValues); + + } + + /** + * Toggles visibility for panes which hold fields for skipgram value (not applicable when calculating for letters) etc., + * sets combobox values to what is applicable ... + * + * @param mode + */ + public void toggleMode(MODE mode) { + if (mode == null) { + mode = currentMode; + } + + logger.info("mode: ", mode.toString()); + + if (mode == MODE.WORD) { + paneWords.setVisible(true); + paneLetters.setVisible(false); + calculateForCB.getItems().setAll(N_GRAM_COMPUTE_FOR_WORDS); + } else if (mode == MODE.LETTER) { + paneWords.setVisible(false); + paneLetters.setVisible(true); + calculateForCB.getItems().setAll(N_GRAM_COMPUTE_FOR_LETTERS); + + // populate with default cvv length value + if (stringLength == null) { + stringLengthTF.setText("1"); + stringLength = 1; + } else { + stringLengthTF.setText(String.valueOf(stringLength)); + } + + // if calculateFor was selected for something other than a word or a lemma -> reset + if (!(calculateFor == CalculateFor.WORD || calculateFor == CalculateFor.LEMMA)) { + // if the user selected something else before selecting ngram for letters, reset that choice + calculateFor = CalculateFor.WORD; + calculateForCB.getSelectionModel().select("različnica"); + } + } + + // override if orth mode, allow only word + if (corpus.isGosOrthMode()) { + calculateForCB.getItems().setAll(N_GRAM_COMPUTE_FOR_WORDS_ORTH); + msdTF.setDisable(true); + } else { + msdTF.setDisable(false); + } + } + + private void compute() { + Filter filter = new Filter(); + filter.setNgramValue(ngramValue); + filter.setCalculateFor(calculateFor); + filter.setMsd(msd); + filter.setTaxonomy(Tax.getTaxonomyCodes(taxonomy, corpus.getCorpusType())); + filter.setAl(AnalysisLevel.STRING_LEVEL); + filter.setSkipValue(skipValue); + filter.setIsCvv(calculateCvv); + filter.setSolarFilters(solarFiltersMap); + + if (ngramValue != null && ngramValue == 0) { + filter.setStringLength(stringLength); + } + + String message = Validation.validateForStringLevel(filter); + if (message == null) { + // no errors + logger.info("Executing: ", filter.toString()); + StatisticsNew statistic = new StatisticsNew(corpus, filter, useDb); + execute(statistic); + } else { + logAlert(message); + showAlert(Alert.AlertType.ERROR, "Prosim izpolnite polja:", message); + } + } + + private void logAlert(String alert) { + logger.info("alert: " + alert); + } + + private void openHelpWebsite(){ + hostService.showDocument(Messages.HELP_URL); + } + + public Corpus getCorpus() { + return corpus; + } + + public void setCorpus(Corpus corpus) { + this.corpus = corpus; + + if (corpus.getCorpusType() != CorpusType.SOLAR) { + setSelectedFiltersLabel(null); + } else { + setSelectedFiltersLabel("/"); + } + } + + public void setSelectedFiltersLabel(String content) { + if (content != null) { + solarFilters.setVisible(true); + selectedFiltersLabel.setVisible(true); + selectedFiltersLabel.setText(content); + } else { + solarFilters.setVisible(false); + selectedFiltersLabel.setVisible(false); + } + } + + private void execute(StatisticsNew statistic) { + logger.info("Started execution: ", statistic.getFilter()); + + Collection corpusFiles = statistic.getCorpus().getDetectedCorpusFiles(); + boolean corpusIsSplit = corpusFiles.size() > 1; + + final Task task = new Task() { + @SuppressWarnings("Duplicates") + @Override + protected Void call() throws Exception { + long i = 0; + for (File f : corpusFiles) { + readXML(f.toString(), statistic); + i++; + this.updateProgress(i, corpusFiles.size()); + this.updateMessage(String.format(ONGOING_NOTIFICATION_ANALYZING_FILE_X_OF_Y, i, corpusFiles.size(), f.getName())); + } + + return null; + } + }; + + ngramProgressBar.progressProperty().bind(task.progressProperty()); + progressLabel.textProperty().bind(task.messageProperty()); + + task.setOnSucceeded(e -> { + try { + boolean successullySaved = statistic.saveResultToDisk(); + if (successullySaved) { + showAlert(Alert.AlertType.INFORMATION, Messages.NOTIFICATION_ANALYSIS_COMPLETED); + } else { + showAlert(Alert.AlertType.INFORMATION, Messages.NOTIFICATION_ANALYSIS_COMPLETED_NO_RESULTS); + } + } catch (UnsupportedEncodingException e1) { + showAlert(Alert.AlertType.ERROR, ERROR_WHILE_SAVING_RESULTS_TO_CSV); + logger.error("Error while saving", e1); + } + + ngramProgressBar.progressProperty().unbind(); + ngramProgressBar.setStyle(Settings.FX_ACCENT_OK); + progressLabel.textProperty().unbind(); + progressLabel.setText(""); + }); + + task.setOnFailed(e -> { + showAlert(Alert.AlertType.ERROR, ERROR_WHILE_EXECUTING); + logger.error("Error while executing", e); + ngramProgressBar.progressProperty().unbind(); + ngramProgressBar.setProgress(0.0); + ngramProgressBar.setStyle(Settings.FX_ACCENT_NOK); + progressLabel.textProperty().unbind(); + progressLabel.setText(""); + }); + + final Thread thread = new Thread(task, "task"); + thread.setDaemon(true); + thread.start(); + } + + public void setSolarFiltersMap(HashMap> solarFiltersMap) { + this.solarFiltersMap = solarFiltersMap; + } + public void setHostServices(HostServices hostServices){ + this.hostService = hostServices; + } +} diff --git a/src/main/java/gui/ValidationUtil.java b/src/main/java/gui/ValidationUtil.java new file mode 100644 index 0000000..9a2cdfc --- /dev/null +++ b/src/main/java/gui/ValidationUtil.java @@ -0,0 +1,77 @@ +package gui; + +import java.io.File; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.math.NumberUtils; + +public class ValidationUtil { + + public static boolean isNumber(String value) { + return NumberUtils.isCreatable(value); + } + + /** + * Checks if an object is empty or null. Null part is especially important, + * since Java's built-in isEmpty() methods don't check for this condition + * and throw a nullPointerException as a result. + *

+ * Supported structures: + *

    + *
  • String: empty if null or length is zero
  • + *
  • List: empty if null or size() == 0
  • + *
  • Map: empty if null or if it contains no keys, or if all keys map to an empty value
  • + *
+ */ + public static boolean isEmpty(Object o) { + if (o == null) { + return true; + } + + if (o instanceof String) { + if (((String) o).length() == 0) { + return true; + } + } + + if (o instanceof List) { + if (((List) o).isEmpty()) { + return true; + } + } + + if (o instanceof Map) { + if (((Map) o).keySet().isEmpty()) { + return true; + } else { + for (Object val : ((Map) o).values()) { + if (!isEmpty(val)) { + // if map contains any value that isn't empty, the map isn't considered empty + return false; + } + } + } + } + + return false; + } + + public static boolean isNotEmpty(Object o) { + return !isEmpty(o); + } + + /** + * Checks whether a given File is a folder for which we have appropriate permission + */ + public static boolean isValidDirectory(File f) { + return f.isDirectory() && f.canRead() && f.canWrite(); + } + + /** + * Checks whether a given File is a folder for which we have appropriate permission + */ + public static boolean isReadableDirectory(File f) { + return f.isDirectory() && f.canRead(); + } +} diff --git a/src/main/java/gui/WordFormationTab.java b/src/main/java/gui/WordFormationTab.java new file mode 100644 index 0000000..81391dd --- /dev/null +++ b/src/main/java/gui/WordFormationTab.java @@ -0,0 +1,208 @@ +package gui; + +import static alg.XML_processing.*; +import static gui.GUIController.*; +import static gui.Messages.*; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; + +import javafx.application.HostServices; +import javafx.scene.control.*; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.controlsfx.control.CheckComboBox; + +import data.*; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.concurrent.Task; +import javafx.fxml.FXML; +import javafx.scene.layout.AnchorPane; + +@SuppressWarnings("Duplicates") +public class WordFormationTab { + public final static Logger logger = LogManager.getLogger(WordFormationTab.class); + + public AnchorPane wordAnalysisTabPane; + + @FXML + public Label selectedFiltersLabel; + @FXML + public Label solarFilters; + + @FXML + private CheckComboBox taxonomyCCB; + private ArrayList taxonomy; + + @FXML + private Button computeB; + + @FXML + public ProgressBar ngramProgressBar; + @FXML + public Label progressLabel; + + @FXML + private Hyperlink helpH; + + private Corpus corpus; + private HashMap> solarFiltersMap; + private HostServices hostService; + + // after header scan + private ObservableList taxonomyCCBValues; + private CorpusType currentCorpusType; + private boolean useDb; + + + public void init() { + // taxonomy + if (Tax.getCorpusTypesWithTaxonomy().contains(corpus.getCorpusType())) { + taxonomyCCB.getItems().removeAll(); + taxonomyCCB.getItems().setAll(corpus.getTaxonomy()); + taxonomyCCB.getCheckModel().getCheckedItems().addListener((ListChangeListener) c -> { + taxonomy = new ArrayList<>(); + ObservableList checkedItems = taxonomyCCB.getCheckModel().getCheckedItems(); + taxonomy.addAll(checkedItems); + logger.info(String.format("Selected taxonomy: %s", StringUtils.join(checkedItems, ","))); + }); + taxonomyCCB.getCheckModel().clearChecks(); + } else { + taxonomyCCB.setDisable(true); + } + + computeB.setOnAction(e -> { + compute(); + logger.info("compute button"); + }); + + helpH.setOnAction(e -> openHelpWebsite()); + } + + private void compute() { + Filter filter = new Filter(); + filter.setNgramValue(1); + filter.setCalculateFor(CalculateFor.MORPHOSYNTACTIC_PROPERTY); + filter.setTaxonomy(Tax.getTaxonomyCodes(taxonomy, corpus.getCorpusType())); + filter.setAl(AnalysisLevel.STRING_LEVEL); + filter.setSkipValue(0); + filter.setMsd(new ArrayList<>()); + filter.setIsCvv(false); + filter.setSolarFilters(solarFiltersMap); + + String message = Validation.validateForStringLevel(filter); + if (message == null) { + // no errors + logger.info("Executing: ", filter.toString()); + StatisticsNew statistic = new StatisticsNew(corpus, filter, useDb); + execute(statistic); + } else { + logAlert(message); + showAlert(Alert.AlertType.ERROR, "Prosim izpolnite polja:", message); + } + } + + private void openHelpWebsite(){ + hostService.showDocument(Messages.HELP_URL); + } + + private void execute(StatisticsNew statistic) { + logger.info("Started execution: ", statistic.getFilter()); + + Collection corpusFiles = statistic.getCorpus().getDetectedCorpusFiles(); + + final Task task = new Task() { + @SuppressWarnings("Duplicates") + @Override + protected Void call() throws Exception { + long i = 0; + for (File f : corpusFiles) { + readXML(f.toString(), statistic); + i++; + this.updateProgress(i, corpusFiles.size()); + this.updateMessage(String.format(ONGOING_NOTIFICATION_ANALYZING_FILE_X_OF_Y, i, corpusFiles.size(), f.getName())); + } + + return null; + } + }; + + ngramProgressBar.progressProperty().bind(task.progressProperty()); + progressLabel.textProperty().bind(task.messageProperty()); + + task.setOnSucceeded(e -> { + try { + // first, we have to recalculate all occurrences to detailed statistics + boolean successullySaved = statistic.recalculateAndSaveResultToDisk(); + + if (successullySaved) { + showAlert(Alert.AlertType.INFORMATION, Messages.NOTIFICATION_ANALYSIS_COMPLETED); + } else { + showAlert(Alert.AlertType.INFORMATION, Messages.NOTIFICATION_ANALYSIS_COMPLETED_NO_RESULTS); + } + } catch (UnsupportedEncodingException e1) { + showAlert(Alert.AlertType.ERROR, ERROR_WHILE_SAVING_RESULTS_TO_CSV); + logger.error("Error while saving", e1); + } + + ngramProgressBar.progressProperty().unbind(); + ngramProgressBar.setStyle(Settings.FX_ACCENT_OK); + progressLabel.textProperty().unbind(); + progressLabel.setText(""); + }); + + task.setOnFailed(e -> { + showAlert(Alert.AlertType.ERROR, ERROR_WHILE_EXECUTING); + logger.error("Error while executing", e); + ngramProgressBar.progressProperty().unbind(); + ngramProgressBar.setProgress(0.0); + ngramProgressBar.setStyle(Settings.FX_ACCENT_NOK); + progressLabel.textProperty().unbind(); + progressLabel.setText(""); + }); + + final Thread thread = new Thread(task, "task"); + thread.setDaemon(true); + thread.start(); + } + + private void logAlert(String alert) { + logger.info("alert: " + alert); + } + + + public void setCorpus(Corpus corpus) { + this.corpus = corpus; + + if (corpus.getCorpusType() != CorpusType.SOLAR) { + setSelectedFiltersLabel(null); + } else { + setSelectedFiltersLabel("/"); + } + } + + public void setSelectedFiltersLabel(String content) { + if (content != null) { + solarFilters.setVisible(true); + selectedFiltersLabel.setVisible(true); + selectedFiltersLabel.setText(content); + } else { + solarFilters.setVisible(false); + selectedFiltersLabel.setVisible(false); + } + } + + public void setSolarFiltersMap(HashMap> solarFiltersMap) { + this.solarFiltersMap = solarFiltersMap; + } + + public void setHostServices(HostServices hostServices){ + this.hostService = hostServices; + } +} diff --git a/src/main/java/gui/WordLevelTab.java b/src/main/java/gui/WordLevelTab.java new file mode 100644 index 0000000..680969e --- /dev/null +++ b/src/main/java/gui/WordLevelTab.java @@ -0,0 +1,207 @@ +package gui; + +import static alg.XML_processing.*; +import static gui.GUIController.*; +import static gui.Messages.*; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; + +import javafx.application.HostServices; +import javafx.scene.control.*; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.controlsfx.control.CheckComboBox; + +import data.*; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.concurrent.Task; +import javafx.fxml.FXML; +import javafx.scene.layout.AnchorPane; + +@SuppressWarnings("Duplicates") +public class WordLevelTab { + public final static Logger logger = LogManager.getLogger(WordLevelTab.class); + + public AnchorPane wordLevelAnalysisTabPane; + + @FXML + public Label selectedFiltersLabel; + @FXML + public Label solarFilters; + + @FXML + private CheckComboBox taxonomyCCB; + private ArrayList taxonomy; + + @FXML + private Button computeB; + + @FXML + public ProgressBar ngramProgressBar; + @FXML + public Label progressLabel; + + @FXML + private Hyperlink helpH; + + private Corpus corpus; + private HashMap> solarFiltersMap; + private HostServices hostService; + + // after header scan + private ObservableList taxonomyCCBValues; + private CorpusType currentCorpusType; + private boolean useDb; + + + public void init() { + // taxonomy + if (Tax.getCorpusTypesWithTaxonomy().contains(corpus.getCorpusType())) { + taxonomyCCB.getItems().removeAll(); + taxonomyCCB.getItems().setAll(corpus.getTaxonomy()); + taxonomyCCB.getCheckModel().getCheckedItems().addListener((ListChangeListener) c -> { + taxonomy = new ArrayList<>(); + ObservableList checkedItems = taxonomyCCB.getCheckModel().getCheckedItems(); + taxonomy.addAll(checkedItems); + logger.info(String.format("Selected taxonomy: %s", StringUtils.join(checkedItems, ","))); + }); + taxonomyCCB.getCheckModel().clearChecks(); + } else { + taxonomyCCB.setDisable(true); + } + + computeB.setOnAction(e -> { + compute(); + logger.info("compute button"); + }); + + helpH.setOnAction(e -> openHelpWebsite()); + } + + private void openHelpWebsite(){ + hostService.showDocument(Messages.HELP_URL); + } + private void compute() { + Filter filter = new Filter(); + filter.setNgramValue(1); + filter.setCalculateFor(CalculateFor.WORD); + filter.setTaxonomy(Tax.getTaxonomyCodes(taxonomy, corpus.getCorpusType())); + filter.setAl(AnalysisLevel.WORD_LEVEL); + filter.setSkipValue(0); + filter.setMsd(new ArrayList<>()); + filter.setIsCvv(false); + filter.setSolarFilters(solarFiltersMap); + + String message = Validation.validateForStringLevel(filter); + if (message == null) { + // no errors + logger.info("Executing: ", filter.toString()); + StatisticsNew statistic = new StatisticsNew(corpus, filter, useDb); + execute(statistic); + } else { + logAlert(message); + showAlert(Alert.AlertType.ERROR, "Prosim izpolnite polja:", message); + } + } + + private void execute(StatisticsNew statistic) { + logger.info("Started execution: ", statistic.getFilter()); + + Collection corpusFiles = statistic.getCorpus().getDetectedCorpusFiles(); + + final Task task = new Task() { + @SuppressWarnings("Duplicates") + @Override + protected Void call() throws Exception { + long i = 0; + for (File f : corpusFiles) { + readXML(f.toString(), statistic); + i++; + this.updateProgress(i, corpusFiles.size()); + this.updateMessage(String.format(ONGOING_NOTIFICATION_ANALYZING_FILE_X_OF_Y, i, corpusFiles.size(), f.getName())); + } + + return null; + } + }; + + ngramProgressBar.progressProperty().bind(task.progressProperty()); + progressLabel.textProperty().bind(task.messageProperty()); + + task.setOnSucceeded(e -> { + try { + // first, we have to recalculate all occurrences to detailed statistics + boolean successullySaved = statistic.saveResultNestedToDisk(); + + if (successullySaved) { + showAlert(Alert.AlertType.INFORMATION, Messages.NOTIFICATION_ANALYSIS_COMPLETED); + } else { + showAlert(Alert.AlertType.INFORMATION, Messages.NOTIFICATION_ANALYSIS_COMPLETED_NO_RESULTS); + } + } catch (UnsupportedEncodingException e1) { + showAlert(Alert.AlertType.ERROR, ERROR_WHILE_SAVING_RESULTS_TO_CSV); + logger.error("Error while saving", e1); + } + + ngramProgressBar.progressProperty().unbind(); + ngramProgressBar.setStyle(Settings.FX_ACCENT_OK); + progressLabel.textProperty().unbind(); + progressLabel.setText(""); + }); + + task.setOnFailed(e -> { + showAlert(Alert.AlertType.ERROR, ERROR_WHILE_EXECUTING); + logger.error("Error while executing", e); + ngramProgressBar.progressProperty().unbind(); + ngramProgressBar.setProgress(0.0); + ngramProgressBar.setStyle(Settings.FX_ACCENT_NOK); + progressLabel.textProperty().unbind(); + progressLabel.setText(""); + }); + + final Thread thread = new Thread(task, "task"); + thread.setDaemon(true); + thread.start(); + } + + private void logAlert(String alert) { + logger.info("alert: " + alert); + } + + + public void setCorpus(Corpus corpus) { + this.corpus = corpus; + + if (corpus.getCorpusType() != CorpusType.SOLAR) { + setSelectedFiltersLabel(null); + } else { + setSelectedFiltersLabel("/"); + } + } + + public void setSelectedFiltersLabel(String content) { + if (content != null) { + solarFilters.setVisible(true); + selectedFiltersLabel.setVisible(true); + selectedFiltersLabel.setText(content); + } else { + solarFilters.setVisible(false); + selectedFiltersLabel.setVisible(false); + } + } + + public void setSolarFiltersMap(HashMap> solarFiltersMap) { + this.solarFiltersMap = solarFiltersMap; + } + + public void setHostServices(HostServices hostServices){ + this.hostService = hostServices; + } +} diff --git a/src/main/java/manifest/META-INF/MANIFEST.MF b/src/main/java/manifest/META-INF/MANIFEST.MF new file mode 100644 index 0000000..d2c5d1f --- /dev/null +++ b/src/main/java/manifest/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: gui.GUIController + diff --git a/src/main/java/util/ByteUtils.java b/src/main/java/util/ByteUtils.java new file mode 100644 index 0000000..90f2a8f --- /dev/null +++ b/src/main/java/util/ByteUtils.java @@ -0,0 +1,25 @@ +package util; + +import java.nio.ByteBuffer; + +public class ByteUtils { + + /* + * Taken from StackOverflow + */ + public static byte[] longToBytes(long x) { + ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); + buffer.putLong(x); + return buffer.array(); + } + + /* + * Taken from StackOverflow + */ + public static long bytesToLong(byte[] bytes) { + ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); + buffer.put(bytes); + buffer.flip();//need flip + return buffer.getLong(); + } +} diff --git a/src/main/java/util/Combinations.java b/src/main/java/util/Combinations.java new file mode 100644 index 0000000..3cb12dc --- /dev/null +++ b/src/main/java/util/Combinations.java @@ -0,0 +1,46 @@ +package util; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.stream.IntStream; + +public class Combinations { + private static HashSet> result = new HashSet<>(); + + + /* arr[] ---> Input Array + data[] ---> Temporary array to store current combination + start & end ---> Staring and Ending indexes in arr[] + index ---> Current index in data[] + r ---> Size of a combination to be printed */ + static void combinationUtil(int arr[], Integer data[], int start, int end, int index, int combinationLength) { + // Current combination is ready to be printed, print it + if (index == combinationLength) { + result.add(new HashSet<>(Arrays.asList(data))); + return; + } + + // replace index with all possible elements. The condition + // "end-i+1 >= r-index" makes sure that including one element + // at index will make a combination with remaining elements + // at remaining positions + for (int i = start; i <= end && end - i + 1 >= combinationLength - index; i++) { + data[index] = arr[i]; + combinationUtil(arr, data, i + 1, end, index + 1, combinationLength); + } + } + + public static HashSet> generateIndices(int maxNOfIndices) { + result = new HashSet<>(); + int[] arr = IntStream.range(1, maxNOfIndices).toArray(); + for (int i = 1; i < maxNOfIndices - 1; i++) { + // A temporary array to store all combination one by one + combinationUtil(arr, new Integer[i], 0, arr.length - 1, 0, i); + } + + // also add an empty one for X.... (all of this type) + result.add(new HashSet<>()); + + return result; + } +} diff --git a/src/main/java/util/Export.java b/src/main/java/util/Export.java new file mode 100644 index 0000000..f11c656 --- /dev/null +++ b/src/main/java/util/Export.java @@ -0,0 +1,267 @@ +package util; + +import static util.Util.*; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.*; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.lang3.tuple.Pair; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import data.Enums.WordLevelType; + +@SuppressWarnings("unchecked") +public class Export { + public static void SetToJSON(Set>> set) { + JSONArray wrapper = new JSONArray(); + + for (Pair> p : set) { + JSONArray data_wrapper = new JSONArray(); + JSONObject metric = new JSONObject(); + + String title = p.getLeft(); + Map map = p.getRight(); + + if (map.isEmpty()) + continue; + + long total = Util.mapSumFrequencies(map); + + for (Map.Entry e : map.entrySet()) { + JSONObject data_entry = new JSONObject(); + data_entry.put("word", e.getKey()); + data_entry.put("frequency", e.getValue()); + data_entry.put("percent", formatNumberAsPercent((double) e.getValue() / total)); + + data_wrapper.add(data_entry); + } + + metric.put("Title", title); + metric.put("data", data_wrapper); + wrapper.add(metric); + } + + try (FileWriter file = new FileWriter("statistics.json")) { + file.write(wrapper.toJSONString()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static String SetToCSV(Set>> set, File resultsPath, LinkedHashMap headerInfoBlock) { + //Delimiter used in CSV file + String NEW_LINE_SEPARATOR = "\n"; + + //CSV file header + Object[] FILE_HEADER = {"word", "frequency", "percent"}; + + String fileName = ""; + + for (Pair> p : set) { + String title = p.getLeft(); + fileName = title.replace(": ", "-"); + fileName = fileName.replace(" ", "_").concat(".csv"); + + fileName = resultsPath.toString().concat(File.separator).concat(fileName); + + Map map = p.getRight(); + + if (map.isEmpty()) + continue; + + long total = Util.mapSumFrequencies(map); + + OutputStreamWriter fileWriter = null; + CSVPrinter csvFilePrinter = null; + + //Create the CSVFormat object with "\n" as a record delimiter + CSVFormat csvFileFormat = CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR).withDelimiter(';'); + + try { + //initialize FileWriter object + fileWriter = new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8); + + //initialize CSVPrinter object + csvFilePrinter = new CSVPrinter(fileWriter, csvFileFormat); + + // write info block + printHeaderInfo(csvFilePrinter, headerInfoBlock); + + //Create CSV file header + csvFilePrinter.printRecord(FILE_HEADER); + + for (Map.Entry e : map.entrySet()) { + List dataEntry = new ArrayList<>(); + dataEntry.add(e.getKey()); + dataEntry.add(e.getValue().toString()); + dataEntry.add(formatNumberAsPercent((double) e.getValue() / total)); + csvFilePrinter.printRecord(dataEntry); + } + } catch (Exception e) { + System.out.println("Error in CsvFileWriter!"); + e.printStackTrace(); + } finally { + try { + if (fileWriter != null) { + fileWriter.flush(); + fileWriter.close(); + } + if (csvFilePrinter != null) { + csvFilePrinter.close(); + } + } catch (IOException e) { + System.out.println("Error while flushing/closing fileWriter/csvPrinter!"); + e.printStackTrace(); + } + } + } + + return fileName; + } + + public static String SetToCSV(String title, Object[][] result, File resultsPath, LinkedHashMap headerInfoBlock) { + //Delimiter used in CSV file + String NEW_LINE_SEPARATOR = "\n"; + + //CSV file header + Object[] FILE_HEADER = {"word", "frequency", "percent"}; + + String fileName = ""; + + fileName = title.replace(": ", "-"); + fileName = fileName.replace(" ", "_").concat(".csv"); + + fileName = resultsPath.toString().concat(File.separator).concat(fileName); + + OutputStreamWriter fileWriter = null; + CSVPrinter csvFilePrinter = null; + + //Create the CSVFormat object with "\n" as a record delimiter + CSVFormat csvFileFormat = CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR).withDelimiter(';'); + + try { + //initialize FileWriter object + fileWriter = new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8); + + //initialize CSVPrinter object + csvFilePrinter = new CSVPrinter(fileWriter, csvFileFormat); + + // write info block + printHeaderInfo(csvFilePrinter, headerInfoBlock); + + //Create CSV file header + csvFilePrinter.printRecord(FILE_HEADER); + + for (Object[] resultEntry : result) { + List dataEntry = new ArrayList<>(); + dataEntry.add(resultEntry[0]); + dataEntry.add(resultEntry[1]); + dataEntry.add(formatNumberAsPercent(resultEntry[2])); + csvFilePrinter.printRecord(dataEntry); + } + } catch (Exception e) { + System.out.println("Error in CsvFileWriter!"); + e.printStackTrace(); + } finally { + try { + if (fileWriter != null) { + fileWriter.flush(); + fileWriter.close(); + } + if (csvFilePrinter != null) { + csvFilePrinter.close(); + } + } catch (IOException e) { + System.out.println("Error while flushing/closing fileWriter/csvPrinter!"); + e.printStackTrace(); + } + } + + return fileName; + } + + public static String nestedMapToCSV(String title, Map>> result, File resultsPath, LinkedHashMap headerInfoBlock) { + //Delimiter used in CSV file + String NEW_LINE_SEPARATOR = "\n"; + + //CSV file header + Object[] FILE_HEADER = {"type", "key", "word", "frequency"}; + + String fileName = ""; + + fileName = title.replace(": ", "-"); + fileName = fileName.replace(" ", "_").concat(".csv"); + + fileName = resultsPath.toString().concat(File.separator).concat(fileName); + + OutputStreamWriter fileWriter = null; + CSVPrinter csvFilePrinter = null; + + //Create the CSVFormat object with "\n" as a record delimiter + CSVFormat csvFileFormat = CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR).withDelimiter(';'); + + try { + //initialize FileWriter object + fileWriter = new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8); + + //initialize CSVPrinter object + csvFilePrinter = new CSVPrinter(fileWriter, csvFileFormat); + + // write info block + printHeaderInfo(csvFilePrinter, headerInfoBlock); + + //Create CSV file header + csvFilePrinter.printRecord(FILE_HEADER); + + for (Map.Entry>> typeEntry : result.entrySet()) { + for (Map.Entry> keyWordEntry : typeEntry.getValue().entrySet()) { + for (Map.Entry calculationResults : keyWordEntry.getValue().entrySet()) { + List values = new ArrayList(); + values.add(typeEntry.getKey().getName()); + values.add(keyWordEntry.getKey()); + values.add(calculationResults.getKey()); + values.add(calculationResults.getValue()); + csvFilePrinter.printRecord(values); + } + } + } + } catch (Exception e) { + System.out.println("Error in CsvFileWriter!"); + e.printStackTrace(); + } finally { + try { + if (fileWriter != null) { + fileWriter.flush(); + fileWriter.close(); + } + if (csvFilePrinter != null) { + csvFilePrinter.close(); + } + } catch (IOException e) { + System.out.println("Error while flushing/closing fileWriter/csvPrinter!"); + e.printStackTrace(); + } + } + + return fileName; + } + + private static void printHeaderInfo(CSVPrinter csvFilePrinter, LinkedHashMap headerInfoBlock) throws IOException { + for (Map.Entry entry : headerInfoBlock.entrySet()) { + List values = new ArrayList(); + values.add(entry.getKey()); + values.add(entry.getValue()); + csvFilePrinter.printRecord(values); + } + + // 2 empty lines + List values = new ArrayList(); + csvFilePrinter.printRecord(values); + csvFilePrinter.printRecord(values); + + } +} diff --git a/src/main/java/util/Key.java b/src/main/java/util/Key.java new file mode 100644 index 0000000..2ddaf4a --- /dev/null +++ b/src/main/java/util/Key.java @@ -0,0 +1,31 @@ +package util; + +public class Key /*implements Comparable */ { + // private final String value; + // + // Key(String value) { + // this.value = value; + // } + // + // @Override + // public int compareTo(Key o) { + // return Objects.compare(this.value, o.value); + // } + // + // @Override + // public boolean equals(Object o) { + // if (this.equals(o)) { + // return true; + // } + // if (o == null || getClass() != o.getClass()) { + // return false; + // } + // Key key = (Key) o; + // return Objects.equals(value, key.value); + // } + // + // @Override + // public int hashCode() { + // return 0; + // } +} \ No newline at end of file diff --git a/src/main/java/util/TimeWatch.java b/src/main/java/util/TimeWatch.java new file mode 100644 index 0000000..cf30ff7 --- /dev/null +++ b/src/main/java/util/TimeWatch.java @@ -0,0 +1,63 @@ +package util; + +import java.util.concurrent.TimeUnit; + +/** + * Adapted from http://memorynotfound.com/calculating-elapsed-time-java/ + */ +public class TimeWatch { + + private long starts; + + private TimeWatch() { + reset(); + } + + public static TimeWatch start() { + return new TimeWatch(); + } + + private TimeWatch reset() { + starts = System.nanoTime(); + return this; + } + + private long time() { + long ends = System.nanoTime(); + return ends - starts; + } + + private long time(TimeUnit unit) { + return unit.convert(time(), TimeUnit.NANOSECONDS); + } + + private String toMinuteSeconds() { + return String.format("%d min, %d sec", time(TimeUnit.MINUTES), + time(TimeUnit.SECONDS) - time(TimeUnit.MINUTES)); + } + + public String toFullTime() { + long hours = time(TimeUnit.HOURS); + long minutes = time(TimeUnit.MINUTES) - TimeUnit.HOURS.toMinutes(hours); + long seconds = time(TimeUnit.SECONDS) - TimeUnit.HOURS.toSeconds(hours) - TimeUnit.MINUTES.toSeconds(minutes); + long milliseconds = time(TimeUnit.MILLISECONDS) - TimeUnit.HOURS.toMillis(hours) - TimeUnit.MINUTES.toMillis(minutes) - TimeUnit.SECONDS.toMillis(seconds); + + return String.format("%d h, %d min, %d s, %d ms", hours, minutes, seconds, milliseconds); + } + + public String toString() { + + return "Elapsed Time in nano seconds: "; + } + + private void exampleUsage() { + TimeWatch watch = TimeWatch.start(); + + // do something... + + System.out.println("Elapsed Time custom format: " + watch.toMinuteSeconds()); + System.out.println("Elapsed Time in seconds: " + watch.time(TimeUnit.SECONDS)); + System.out.println("Elapsed Time in nano seconds: " + watch.time()); + + } +} \ No newline at end of file diff --git a/src/main/java/util/Util.java b/src/main/java/util/Util.java new file mode 100644 index 0000000..fa35d02 --- /dev/null +++ b/src/main/java/util/Util.java @@ -0,0 +1,225 @@ +package util; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.text.MessageFormat; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Stream; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import data.Settings; +import gui.GUIController; +import gui.ValidationUtil; + +public class Util { + public final static Logger logger = LogManager.getLogger(Util.class); + + + public static String toReadableTime(long time) { + long hours = time(TimeUnit.HOURS, time); + long minutes = time(TimeUnit.MINUTES, time) - TimeUnit.HOURS.toMinutes(hours); + long seconds = time(TimeUnit.SECONDS, time) - TimeUnit.HOURS.toSeconds(hours) - TimeUnit.MINUTES.toSeconds(minutes); + long milliseconds = time(TimeUnit.MILLISECONDS, time) - TimeUnit.HOURS.toMillis(hours) - TimeUnit.MINUTES.toMillis(minutes) - TimeUnit.SECONDS.toMillis(seconds); + long microseconds = time(TimeUnit.MICROSECONDS, time) - TimeUnit.HOURS.toMicros(hours) - TimeUnit.MINUTES.toMicros(minutes) - TimeUnit.SECONDS.toMicros(seconds) - TimeUnit.MILLISECONDS.toMicros(milliseconds); + long nanoseconds = time(TimeUnit.NANOSECONDS, time) - TimeUnit.HOURS.toNanos(hours) - TimeUnit.MINUTES.toNanos(minutes) - TimeUnit.SECONDS.toNanos(seconds) - TimeUnit.MILLISECONDS.toNanos(milliseconds) - TimeUnit.MICROSECONDS.toNanos(microseconds); + + return String.format("%d h, %d min, %d s, %d ms, %d µs, %d ns", hours, minutes, seconds, milliseconds, microseconds, nanoseconds); + } + + private static long time(TimeUnit unit, long t) { + return unit.convert(t, TimeUnit.NANOSECONDS); + } + + /** + * Converts a number to a more readable format. + * 12345 -> 12.345 + * 12345,678 -> 12.345,67 + * + * @param o byte, double, float, int,long, short + * + * @return number formatted with thousands separator and 2 decimal places (floats) + */ + private static String formatNumberReadable(Object o) { + if (isInstanceOfInteger(o)) + return String.format("%,d", o); + else if (isInstanceOfFloat(o)) + return String.format("%,.2f", o); + else + return "- invalid input format -"; + } + + public static String formatNumberAsPercent(Object o) { + return MessageFormat.format("{0,number,#.###%}", o); + } + + private static boolean isInstanceOfInteger(Object o) { + Set> types = new HashSet<>(); + types.add(Byte.class); + types.add(Short.class); + types.add(Integer.class); + types.add(Long.class); + + return types.contains(o.getClass()); + } + + private static boolean isInstanceOfFloat(Object o) { + Set> types = new HashSet<>(); + types.add(Float.class); + types.add(Double.class); + + return types.contains(o.getClass()); + } + + public static void printMap(Map map) { + System.out.println("\nkey: value"); + map.forEach((k, v) -> System.out.print(String.format("%s:\t %,8d%n", k, v))); + System.out.println(); + } + + /** + * Generic map converter -> since AtomicLongs aren't as comparable. + * Converts ConcurrentHashMap to HashMap + */ + public static Map atomicInt2StringAndInt(Map map) { + Map m = new HashMap(); + + for (Map.Entry e : map.entrySet()) { + m.put(e.getKey().toString(), ((AtomicLong) e.getValue()).longValue()); + } + + return m; + } + + /** + * Sorts a map in a descending order by value. + */ + public static > Map sortByValue(Map map, int limit) { + /* + sorted() in itself is O(1), since it's an intermediate operation that + doesn't consume the stream, but simply adds an operation to the pipeline. + Once the stream is consumed by a terminal operation, the sort happens and + either + - it doesn't do anything (O(1)) because the stream knows that the + elements are already sorted (because they come from a SortedSet, for example) + - or the stream is not parallel, and it delegates to Arrays.sort() (O(n log n)) + - or the stream is parallel, and it delegates to Arrays.parallelSort() (O(n log n)) + + As of JDK 8, the main sorting algorithm which is also used in standard + stream API implementation for sequential sorting is TimSort. Its worst + case is O(n log n), but it works incredibly fast (with O(n) and quite + small constant) if data is presorted (in forward or reverse direction) + or partially presorted (for example, if you concatenate two sorted lists + and sort them again). + */ + // if limit is set to 0 or less, we take that to mean no limit at all + if (limit <= 0) { + limit = map.size(); + } + + Map result = new LinkedHashMap<>(); + TimeWatch watch = TimeWatch.start(); + + Stream> st = map.entrySet().stream(); + + st.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).limit(limit) + .forEachOrdered(e -> result.put(e.getKey(), e.getValue())); + + if (Settings.PRINT_LOG) { + System.out.println(String.format("Elapsed time for sorting %s items: %s", + formatNumberReadable(result.size()), + watch.toFullTime())); + } + + return result; + } + + public static void printMap(Map map, String title, int number_of_words) { + System.out.println(String.format("\n%s\n------------\nkey: value\tpercent", title)); + map.forEach((k, v) -> + System.out.println(String.format("%s:\t %s\t %s%%", + k, + Util.formatNumberReadable(v), + Util.formatNumberReadable((double) v / number_of_words * 100)))); + System.out.println(); + } + + static long mapSumFrequencies(Map map) { + long sum = 0; + + for (long value : map.values()) { + sum += value; + } + + return sum; + } + + /** + * Used for passing optional integer values for sorting. + */ + public static int getValidInt(int... i) { + if (i == null || i.length < 1 || i[0] <= 0) { + return 0; + } else { + return i[0]; + } + } + + /** + * Check whether a map is empty. It also considers an edge case where map's keys are lists to check if those lists are empty. + */ + public static boolean isMapEmpty(Map map) { + if (map.isEmpty()) { + // default + return true; + } + + // otherwise check if keys map to values that are empty + for (V v : map.values()) { + // todo: generalize to all collections if/when needed + ArrayList vl = new ArrayList((List) v); + if (!vl.isEmpty()) { + return false; + } + } + + return true; + } + + /** + * Returns the location of the main class if possible, otherwise null + */ + public static File getWorkingDirectory() { + // get location of the currently executing class + String path = GUIController.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + + logger.info("working dir path: ", path); + + String decodedPath = null; + try { + decodedPath = URLDecoder.decode(path, "UTF-8"); + } catch (UnsupportedEncodingException e) { + logger.error("decoding: ", e); + // e.printStackTrace(); + } + + if (decodedPath != null) { + File workingDirectory = new File(decodedPath); + + // in case it's a file (class is packaged inside a jar), select its parent folder + workingDirectory = workingDirectory.isFile() ? workingDirectory.getParentFile() : workingDirectory; + + if (ValidationUtil.isReadableDirectory(workingDirectory)) { + logger.info("working dir is ok: ", workingDirectory.getAbsolutePath()); + return workingDirectory; + } + } + + logger.info("working dir returing null"); + return null; + } +} diff --git a/src/main/java/util/db/RDB.java b/src/main/java/util/db/RDB.java new file mode 100644 index 0000000..356f2a7 --- /dev/null +++ b/src/main/java/util/db/RDB.java @@ -0,0 +1,132 @@ +package util.db; + +import static util.ByteUtils.*; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import org.apache.commons.io.FileUtils; +import org.rocksdb.*; + +import util.TimeWatch; + +public class RDB { + + private RocksDB db; + private String path; + private static final String UTF_8 = "UTF-8"; + + public RDB() { + // different dbs i ncase of concurrent calculations + this.path = System.getProperty("java.io.tmpdir") + .concat(File.separator) + .concat(String.format("corpusAnalyzer_db%d", LocalDateTime.now().toString().hashCode())); + + this.db = createDB(); + } + + + private RocksDB createDB() { + RocksDB.loadLibrary(); + + // the Options class contains a set of configurable DB options + // that determines the behaviour of the database. + try (final Options options = new Options()) { + options.setCreateIfMissing(true); + + // a factory method that returns a RocksDB instance + try (final RocksDB rdb = RocksDB.open(options, path)) { + if (db != null) { + return rdb; + } else { + this.db = rdb; + } + } + } catch (RocksDBException e) { + // do some error handling + } + return null; + } + + public void writeBatch(Map results) throws UnsupportedEncodingException { + RocksDB.loadLibrary(); + + // a factory method that returns a RocksDB instance + try (final RocksDB rdb = RocksDB.open(new Options(), path)) { + final WriteBatch wb = new WriteBatch(); + + for (Map.Entry entry : results.entrySet()) { + byte[] key = entry.getKey().getBytes(UTF_8); + long resultValue = entry.getValue().longValue(); + + try { + final byte[] dbValue = rdb.get(key); + if (dbValue != null) { + // value == null if key does not exist in db. + wb.put(key, longToBytes(bytesToLong(dbValue) + resultValue)); + } else { + wb.put(key, longToBytes(entry.getValue().longValue())); + } + } catch (RocksDBException e) { + // TODO: error handling + } + } + TimeWatch watch = TimeWatch.start(); + rdb.write(new WriteOptions(), wb); + System.out.println(String.format("Writing %d entries took: %s", wb.count(), watch.toFullTime())); + } catch (RocksDBException e) { + // do some error handling + } + } + + // public byte[] atomicIntToByteArray(final AtomicLong i) { + // BigInteger bigInt = BigInteger.valueOf(i.intValue()); + // + // return bigInt.toByteArray(); + // } + + public RocksDB getDb() { + return db; + } + + public Map getDump() throws UnsupportedEncodingException { + Map dump = new HashMap<>(); + RocksDB.loadLibrary(); + + // the Options class contains a set of configurable DB options + // that determines the behaviour of the database. + // a factory method that returns a RocksDB instance + try (final RocksDB rdb = RocksDB.open(new Options(), path)) { + try (RocksIterator it = rdb.newIterator()) { + it.seekToFirst(); + // it.next(); + + while (it.isValid()) { + byte[] key = it.key(); + byte[] value = it.value(); + + dump.put(new String(key, UTF_8), new AtomicLong(bytesToLong(value))); + + it.next(); + } + } + } catch (RocksDBException e) { + e.printStackTrace(); + } + + return dump; + } + + public void delete() { + try { + FileUtils.deleteDirectory(new File(path)); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/resources/GOS_small/TEI_GOS_small.xml b/src/main/resources/GOS_small/TEI_GOS_small.xml new file mode 100644 index 0000000..bf78abb --- /dev/null +++ b/src/main/resources/GOS_small/TEI_GOS_small.xml @@ -0,0 +1,68720 @@ + + + + + + + Korpus GOS + GOS Corpus + Operacijo delno financira Evropska unija iz Evropskega socialnega sklada ter Ministrstvo za šolstvo in šport. Operacija se izvaja v okviru Operativnega programa razvoja človeških virov za obdobje 2007/2013, razvojne prioritete: razvoj človeških virov in vseživljenjskega učenja; prednostne usmeritve: izboljšanje kakovosti in učinkovitosti sistemov izobraževanja in usposabljanja 2007/2013. + The operation is partly financed by the European Union, the European Social Fund, and the Ministry of Education and Sport of the Republic of Slovenia. The operation is being carried out within the operational programme Human Resources Development for the period 2007/2013, developmental priorities: improvement of the quality and efficiency of educational and training systems 2007/2013. + + Miro Romih, Amebis + Vodja projekta "Sporazumevanje v slovenskem jeziku. + "Communication in Slovene" project leader. + + + Simon Krek, Amebis, JSI + Koordinator projekta "Sporazumevanje v slovenskem jeziku. + "Communication in Slovene" project coordinator. + + + Ana Zwitter Vitez, Trojina + Koordinatorica gradnje korpusa GOS. + Coordinator of the GOS corpus compilation project. + + + Darinka Verdonik, FERI + Koordinatorica izdelave spletnega konkordančnika GOS. + Coordinator of the GOS corpus web concordancer project. + + + Tomaž Erjavec, JSI + Redakcija zapisa TEI / XML. + TEI / XML corpus encoding. + + + + 1.0 + + + +
+ Amebis, d.o.o., Kamnik + Bakovnik 3 + SI-1241 Kamnik + Slovenia +
+
+ Amebis, d.o.o., Kamnik + Bakovnik 3 + 1241 Kamnik +
+
+ + http://www.slovenscina.eu/ + http://www.korpus-gos.net/ + + +

Avtorske pravice za to izdajo ureja licenca Priznanje avtorstva-Nekomercialno-Deljenje pod enakimi pogoji 3.0.

+

Dovoljeno vam je: reproduciranje, distribuiranje, dajanje v najem in priobčevanje dela javnostipredelati delo Pod naslednjimi pogoji: Priznanje avtorstva — Pri uporabi dela morate navesti izvirnega avtorja na način, ki ga določi izvirni avtor oziroma dajalec licence. V znanstvenih publikacijah to pomeni citiranje ustreznega dela ali del, dostopnih na domači strani projekta, http://www.slovenscina.eu/.Nekomercialno. Tega dela ne smete uporabiti v komercialne namene. Deljenje pod enakimi pogoji — Če spremenite, preoblikujete ali uporabite to delo v svojem delu, lahko distribuirate predelavo dela le pod licenco, ki je enaka tej.

+

This work is licenced under the Attribution-NonCommercial-ShareAlike 3.0.

+

You are free: to Share — to copy, distribute and transmit the workto Remix — to adapt the work Under the following conditions: Attribution — You must attribute the work in the manner specified by the author or licensor. In scientific publications this means citing the relevant publication or publications, referred to on the home page of the project: http://www.slovenscina.eu/.Noncommercial. You may not use this work for commercial purposes.Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same or similar license to this one.

+
+ 2012-03-14 +
+ +

Besedila so pretvorjena v TEI XML iz datotek programa Transcriber.

+

Texts are transformed to TEI XML from Transcriber files.

+
+
+ + +

Projekt Sporazumevanje v slovenskem jeziku

+

Project Communication in Slovene

+
+ + + + + tip diskurza + + javni + + informativno-izobraževalni + + + razvedrilni + + + + nejavni + + nezasebni + + + zasebni + + + + + + kanal + + osebni stik + + + telefon + + + radio + + + televizija + + + + +
+ + + slovenščina + angleščina + nemščina + italijanščina + južnoslovanski jeziki + drugi slovanski jeziki + drugi romanski jeziki + + +
+ + + + + + Splošno predavanje za prvi letnik prevajalstva. + + snemanje + Neža Pahovnik + + + transkripcija + MatejaS + + + + 2009-11-05 + + + + + + + + terenski posnetek + + + 2009-11-05 + + + + + + + + + + + + + + akademski, družboslovje + + + + + + + + + ženski + + LJ + fakulteta ali več + + + + + + + + + LJ + Ljubljana + + + 2009-10-22 + + + + + + + +
+ + + no + začel + bomo + kr + čisto + v + prazgodovini + a + ne + kaj + imamo + pri + nas + ohranjenega + iz + prazgodovine + + + jz + sem + tisto + neandertalsko + piščalko + malo + izpustila + zarad + tega + ker + stvari + niso + čisto + jasne + ne + + + če + ne + gre + to + slučajno + za + ene + + + + + + + + + + kosti + ki + so + ble + mal + preluknane + pač + ni + dokazano + al + je + bla + to + res + izdelana + piščalka + zato + začnemo + z + nečem + kar + je + sigurno + + + s + tole + vaško + situlo + ki + jo + vsi + poznate + in + ste + že + stokrat + + sti + + + slišali + da + je + + + rada + bi + samo + da + se + za + hip + zamislite + a + ne + da + to + sega + kako + daleč + nazaj + to + sega + + + peto + stoletje + pred + našim + štetjem + takrat + doba + ki + je + vladala + se + pač + zgodovinsko + obdobje + je + poimenovano + železna + doba + + + te + situle + so + bile + najdene + v + + bo + + + zelo + takih + bogatih + grobovih + + + to + se + pravi + sklepajo + da + so + tisti + bogatejši + ljudje + premožnejši + imeli + situle + in + so + jih + uporabljali + v + nekih + v + nekakšnih + obredih + in + so + z + njih + z + zajemalko + zajemali + pijačo + + + + + + + + + + eee + iz + tega + časa + so + ohranjena + še + razna + železna + orodja + tudi + pri + nas + grobišča + in + tudi + gradišča + tako + imenovana + na + hribih + + + zdej + če + pogledate + še + bolj + natančno + ta + vzorec + na + vaški + situli + mogoče + tega + pa + res + niste + še + nikoli + pogledali + + + + + + + + + + mo + vidli + če + bo + to + potegnilo + ja + + + + + + + + + + vidite + lahko + da + je + zelo + zelo + natančno + vse + nekej + izrisano + na + tej + vaški + situli + + + v + bistvu + so + tudi + situle + izrisane + iz + tega + sploh + sklepajo + kaj + je + to + + + tale + druga + vrsta + a + ne + kaže + na + to + kako + so + tale + sedi + in + ta + mu + iz + ene + posode + toči + pijačo + + + iz + tega + sklepajo + poglejte + kako + so + vsi + ti + ljudje + oblečeni + imajo + voz + se + pelje + na + vozu + ne + stol + ne + vem + kaj + vse + klobuk + konja + vpreženega + lepo + + + to + se + pravi + zdej + pa + pomislte + pet + peto + stoletje + pred + našim + štetjem + to + je + res + daleč + nazaj + ne + tako + da + res + dragocena + najdba + + + tukile + v + drugi + + vr + + + v + zadnji + vrsti + to + nej + bi + se + izmenjavov + kozorog + koza + kozorog + koza + in + tko + naprej + zadnji + je + pa + panter + + + in + tukejle + ma + pa + človeško + nogo + je + enga + pojedu + ne + + + + + + + + + + ta + slikica + se + ponovi + + + če + imate + potne + liste + predvidevam + da + ja + ne + jo + imate + celo + tole + to + je + ta + slika + ne + tuki + se + začne + tuki + se + nadaljuje + + + seveda + + o + + + očitno + imamo + to + za + enega + izmed + slovenskih + simbolov + + + samo + obrnjeni + so + mal + v + drugo + smer + pa + pomešani + so + + + + + + + + + + tukejle + en + sedi + pa + nogice + mu + dol + s + konja + binglajo + + + + + + + + + + tko + da + izjemno + + i + + + dodelana + ta + slika + + + to + seveda + nima + še + zveze + s + Slovenci + a + ne + takrat + so + živeli + na + tem + območju + tako + imenovani + Veneti + + + ampak + najdeno + je + to + pri + Vačah + torej + na + našem + kulturnem + prostoru + in + lahko + vidimo + kako + daleč + nazaj + sežejo + prvi + prebivalci + + + + + + + + + + tko + no + ta + to + je + vaška + situla + torej + nekakšno + vedro + za + iz + katerega + se + pije + vedro + ki + govori + samo + o + sebi + a + ne + + + če + ne + bi + bilo + tako + natančno + izdelane + te + slike + verjetno + tudi + ne + bi + vedeli + za + kaj + se + je + uporablalo + + nata + + + v + bistvu + se + iz + tega + prepozna + + + + + + + + + + in + potem + zdej + že + mi + nardimo + strašen + preskok + par + stoletij + + + veste + da + so + bli + tud + Kelti + in + Rimljani + na + našem + območju + + + zdej + čisto + na + kratko + samo + tolko + kolker + se + spodobi + za + enega + izobraženca + + + v + kar + pravkar + se + razvijate + a + ne + da + se + ve + pač + da + so + bli + na + našem + ozemlju + so + bila + plemena + Keltov + + + zdej + kdo + so + Kelti + v + to + se + ne + bomo + spuščali + ampak + nekako + tako + se + naj + bi + bili + neki + predniki + se + pravi + to + kar + se + je + iz + Keltov + razvilo + zdej + živi + na + Irskem + recimo + a + ne + tko + pa + na + Škotskem + tko + zlo + posplošeno + povedano + + + no + potem + kar + je + bolj + važno + za + naše + obdobje + pa + so + že + počasi + začeli + prihajati + k + nam + Rimljani + a + ne + vdor + rimskih + plemen + + + in + to + se + je + začelo + kot + vidite + glejte + približno + v + drugem + stoletju + pred + našim + štetjem + + + prvo + mesto + tako + je + bila + Akvileja + ali + Oglej + + + prvo + rimsko + mesto + na + slovenskem + ozemlju + Akvileja + Oglej + + + kasneje + v + zgodovini + veste + da + je + to + mesto + odigralo + veliko + vlogo + kot + neko + središče + krščansko + a + ne + oglejski + patriarh + + + ampak + k + temu + se + vrnemo + kasneje + + + bilo + je + pa + prvo + rimljansko + mesto + + + a + veste + kje + je + Oglej + ? + + + + + + + + + + ja + kje + ? + + + + + + + + + + v + Italiji + ? + + + ja + no + pri + približno + pri + izviru + Soče + a + ne + + + eem + tm + je + zlo + tja + je + zlo + lep + izlet + zelo + lep + sprehod + + + se + vidijo + ti + + ro + + + rimski + ostanki + so + veliki + stebri + so + ohranjeni + zelo + lepo + je + in + drevored + in + tko + + + če + boste + kdaj + po + tistih + koncih + hodili + je + lep + izlet + + + no + potem + cesar + Oktavijan + recimo + je + + o + + + pač + nadaljeval + s + tem + rimskim + osvajanjem + premaknil + mejo + nekje + do + Donave + Rimskega + cesarstva + + + in + v + tistem + času + to + se + pravi + malo + pred + našim + štetjem + pa + okrog + ničle + pa + naprej + so + nastala + rimska + mesta + na + našem + področju + Emona + Celeja + Petovija + vsi + poznamo + a + ne + + + no + in + + na + + + narjen + je + bil + cestni + sistem + s + to + glavno + osjo + kot + vidite + zapisano + do + Karuntuma + + + to + je + blo + pa + eno + mesto + ob + Donavi + ki + je + danes + nekje + na + polovici + poti + med + Dunajem + in + Bratislavo + + + to + se + pravi + ta + cestna + povezava + je + šla + od + morja + od + Jadranskega + morja + praktično + do + tam + kjer + je + današnji + Dunaj + prva + cesta + + + + + + + + + + eee + kaj + se + je + v + rimskih + časih + dogajalo + tukaj + se + s + tem + se + ne + bomo + ukvarjali + ostanki + so + veste + da + v + Lublani + zelo + velik + rimski + zid + lepo + ohranjen + + + zdej + ne + morejo + zgradit + univerzitetne + knjižnice + ker + je + preveč + rimskih + ostankov + in + tako + naprej + + + no + ampak + že + v + petem + in + šestem + stoletju + je + začela + rimska + oblast + slabeti + + + najprej + zaradi + vdorov + germanskih + plemen + s + severa + so + pritisnili + navzdol + in + tako + se + je + pač + to + rimsko + obdobje + pri + nas + kar + hitro + končalo + to + se + pravi + vidite + šeststo + sedemsto + let + nekej + takega + da + so + bili + pri + nas + Rimljani + + + in + začelo + se + je + v + šestem + stoletju + seveda + naseljevanje + + + + + + + + + + Slovanov + a + ne + + + šele + sedaj + pridejo + naši + predniki + na + to + območje + + + + + + + + + + to + tega + se + verjetno + vsega + spominjate + počasi + še + iz + srednje + šole + pač + naselitev + Slovanov + v + dveh + v + dveh + nekako + v + dveh + valovih + in + tudi + v + dveh + časovnih + zaporedjih + + + eni + so + šli + bolj + k + Alpam + a + ne + to + so + bli + recimo + naši + predniki + eni + so + šli + pa + bolj + na + moravsko + stran + v + Panonijo + + + + + + + + + + eee + to + niti + ni + tko + pomembno + najprej + niso + bli + samostojni + a + ne + so + bli + pod + eno + oblastjo + Avarov + + + Avari + so + bli + pa + spet + eno + drugo + ljudstvo + ki + so + se + istočasno + priseljevali + na + to + področje + + + ampak + v + začetku + sedmega + stoletja + so + pa + + z + + + že + začele + nastajati + neke + samostojne + plemenske + zveze + + + verjetno + se + iz + šole + spomnite + neke + Samove + plemenske + zveze + ampak + zdej + ta + trenutek + to + pustimo + eee + na + mmm + pač + mmm + ob + strani + + + ampak + začele + so + se + neke + tvorbe + ki + so + pripeljale + do + prve + slovenske + države + + + + + + + + + + ki + je + pa + bila + + + + + + + + + + ne + države + ne + smemo + reč + ne + neke + samostojne + tvorbe + podobne + državi + ki + se + ji + je + reklo + Karantanija + + + + + + + + + + Karantanija + + + + + + + + + + to + se + pravi + za + za + Karantanijo + važno + da + si + zapomnite + da + je + bla + bila + tvorba + ki + + ne + + + bi + nastala + nekje + v + sedmem + stoletju + + + veste + da + so + zapiski + a + pa + dokumenti + o + teh + prazgodovinskih + praktično + stvareh + se + eem + slabo + ohranjeni + ne + iz + starega + veka + + + ampak + toliko + se + že + da + sklepati + da + pač + približno + se + ve + da + je + ta + Karantanija + bila + + + + da + je + bila + na + začetku + popolnoma + neodvisna + država + + + vendar + to + je + blo + samo + kakšnih + eem + mislim + da + okrog + sto + let + je + bila + neodvisna + + + potem + so + pa + že + prišli + pod + vpliv + Bavarcev + + + ampak + še + kljub + temu + se + govori + da + je + Karantanija + obstajala + tristo + let + + + prvih + sto + let + kot + neodvisna + država + drugih + dvesto + let + pa + kot + neka + tvorba + + sa + + + mmm + z + relativno + samostojnostjo + pod + Bavarci + in + še + kasneje + v + Frankovski + državi + + + to + se + pravi + ni + bila + ves + čas + samostojna + samo + na + začetku + + + takrat + ko + so + Bavarce + prosili + za + neko + pomoč + v + vojnah + so + pač + postali + eem + podložni + njim + + + no + tukaj + se + mi + zdi + en + zanimiv + detajl + + + + + + + + + + eem + torej + kako + so + se + s + temi + Bavarci + dogovorili + ne + + + da + so + jim + pomagali + v + eni + borbi + z + Avari + so + jim + poslali + so + jim + moral + poslat + dva + talca + + + to + sta + bla + bratranca + a + ne + Gorazd + in + Hotimir + + + Gorazd + je + bil + + s + + + + vla + + + eee + knezov + sin + Hotimir + je + bil + pa + njegov + bratranec + torej + + + in + ta + dva + so + potem + Bavarci + pokristjanili + + + zdej + Gorazd + ki + je + bil + pač + dedni + naslednik + je + vladal + samo + tri + leta + in + so + ga + ubili + + + in + tako + je + potem + njegov + bratranec + dejansko + prišel + na + oblast + Hotimir + + + in + v + času + Hotimira + torej + v + Karantaniji + se + je + začelo + pri + nas + pokristjanjevanje + + + temle + zgorej + me + precej + motite + dekleta + če + ne + zamerite + + + zdej + ali + boste + nehale + klepetet + ali + pa + vas + prosm + če + zapustite + prizorišče + ne + + + v + redu + kakor + vam + je + lubše + + + + + + + + + + prosim + ? + + + no + kaj + boste + izbrale + ? + + + + + + + + + + ne + vem + kaj + to + pomeni + + + aha + dobro + + + v + redu + no + ustavli + smo + se + pri + Hotimiru + + + + eee + ki + je + prevzel + oblast + v + Karantaniji + + + in + od + kod + ga + poznamo + od + kod + mi + Hotimira + poznamo + ? + + + + + + + + + + iz + Krsta + seveda + ne + v + Krstu + obravnava + pač + vsebina + tema + Krsta + je + pokristjanjevanje + in + kot + vidte + tud + tukej + in + so + navedeni + trije + upori + seveda + so + se + prebivalci + upirali + pokristjanjevanju + + + eem + ni + šlo + tako + zlahka + ampak + Hotimir + je + bil + tisti + ki + je + pri + tem + vztrajal + + + ker + je + moral + vztrajati + zato + ker + je + bil + predan + za + talca + Bavarcem + in + je + pač + moral + potem + ubogati + kar + so + mu + naročili + + + no + zdej + samo + še + za + eno + orientacijo + + + mmm + to + verjetno + tudi + vsi + se + še + spomnite + + + kje + je + Karantanija + ležala + + + to + seveda + ni + bilo + na + prov + na + območju + Slovenije + današnje + ampak + je + bilo + severno + a + ne + na + območju + današnje + avstrijske + Koroške + in + še + bolj + gor + na + sever + + + + + + + + + + tako + naša + pradomovina + v + nekem + smislu + + + + + + + + + + no + eem + + + + + + + + + + mogoče + mal + preveč + hitim + + + + + + + + + + kot + sem + že + prej + povedala + je + Karantanija + zlo + hitro + izgubila + svoje + samostojnost + + + + + + + + + + in + prišla + pod + eee + bla + vključena + tudi + potem + najprej + pod + bavarskega + kneza + potem + ko + so + pa + Bavarci + izgubili + so + pa + še + prišli + v + Frankovsko + državo + + + + + + + + + + tam + se + je + potem + vse + reorganiziralo + ampak + Karantanija + je + ohranila + neko + plemensko + notranjo + + u + + + ureditev + tako + da + je + na + nek + način + obstala + še + nekaj + stoletij + + + kar + je + najbolj + znano + iz + tega + časa + je + obred + ustoličevanja + koroških + vojvod + a + ne + + + eee + ki + se + je + potem + ohranil + ker + dejansko + potem + vsaj + v + desetem + stoletju + tam + devetsto + petdeset + potem + Karantanije + dejansko + ni + blo + več + niti + v + okviru + Frankovske + države + + + ampak + ta + obred + ustoličevanja + se + je + pa + ohranil + še + petsto + let + + + bili + so + tam + eem + že + čisto + drugi + gospodarji + ampak + nekako + je + ta + tradicija + ostala + a + ne + kar + je + zelo + nenavadno + + + in + je + v + večih + knjigah + tujih + seveda + ta + obred + popisan + in + dokumentiran + + + zdej + kaj + točno + se + je + tam + dogajalo + + + se + pravi + najprej + je + šlo + za + ustoličevanje + karantanskih + knezov + + + Karantanija + je + bla + kneževina + so + imel + kneze + a + ne + + + pač + prvo + prvi + del + prvo + kar + poznamo + je + blo + ustoličevanje + na + knežjem + kamnu + + + zej + če + + z + + + če + pogledamo + kar + hitro + sliko + da + bomo + vedeli + o + čem + govorimo + + + + + + + + + + tole + je + bil + ta + knežji + kamen + ne + + + v + resnici + je + to + kot + vidite + jasno + je + eee + zgornji + del + enega + rimskega + stebra + + + ki + je + bil + prinešen + seveda + za + njih + + s + + + je + + se + + + so + bli + rimski + časi + že + ravno + tako + arhaični + kot + so + danes + za + nas + + + ne + tolk + ampak + blo + je + to + nekej + kar + je + blo + tisoč + let + staro + že + takrat + ne + + + in + to + je + blo + z + enega + bližnega + mesta + eee + rimske + ostaline + so + ta + kamen + prinesli + na + Krnski + grad + + + + predvid + + + predvidoma + je + blo + to + najprej + na + Krnskem + gradu + + + in + so + potem + začeli + tukaj + to + ustoličevanje + knezov + + + zej + to + je + blo + to + je + imelo + simboličen + pomen + a + ne + + + eem + knez + naj + bi + tukej + vladar + Karantancev + je + na + tem + + presto + + + recimo + no + kamnu + pač + sprejel + oblast + iz + rok + ljudstva + + + + + + + + + + kako + + j + + + kaj + kakšen + pomen + je + melo + to + prvotno + + n + + + ni + čisto + jasno + + + ampak + ve + se + da + tud + kasneje + ko + je + bla + oblast + že + dedna + prvotno + ni + bla + dedna + ampak + tudi + ko + je + postala + oblast + dedna + še + vedno + ker + jasno + je + blo + da + bo + sin + nasledil + očeta + + + ampak + ko + se + je + to + zgodilo + še + vedno + je + simbolično + šel + sedet + na + ta + knežji + kamen + in + je + sprejel + pač + eee + voljo + ljudstva + da + jim + bo + da + ga + postavlajo + za + kneza + in + on + jim + je + potem + obljubil + da + bo + dobro + vladal + + + zdej + jasno + klučno + temeljno + vprašanje + v + kakšnem + jeziku + je + to + potekalo + a + ne + se + na + žalost + ne + ve + zarad + tega + ker + ni + ohranjenih + zapisov + + + zej + mi + z + veseljem + sklepamo + in + si + želimo + da + je + blo + to + v + nekem + slovenskem + arhaičnem + jeziku + predvidoma + ja + ker + se + je + začelo + v + Karantaniji + + + in + + p + + + to + je + potem + možno + da + tudi + še + potem + ko + so + koroške + vojvode + ki + niso + bili + več + nujno + slovenskega + izvora + al + to + kar + razumemo + za + slovensko + da + so + da + je + + tak + + + tudi + še + takret + potekal + obred + ustoličevanja + v + slovenščini + + + to + bi + pomenilo + da + so + oni + v + tujem + jeziku + govorili + da + je + bla + slovenščina + kot + tuji + jezik + nek + obredni + jezik + ustoličevanja + kar + je + dokaj + nenavadno + ampak + žal + zej + teh + ni + ohranjenih + eee + + natančnih + zapisov + ki + bi + to + dokumentirali + + + no + ta + knežji + kamen + se + je + seveda + tudi + pojavil + zdej + kot + slovenski + nacionalni + simbol + na + kovancu + našem + + + a + veste + na + katerem + ? + + + ja + vse + to + pa + mmm + to + se + pa + dobro + spoznate + + + + + + + + + + + no + potem + pa + je + tukaj + še + vojvodski + prestol + a + ne + ki + je + pa + nekej + drugega + + + aha + zdej + je + ta + + ki + + + kje + je + zdej + knežji + kamen + + + dolgo + je + bil + v + muzeju + nekje + v + Celovcu + Slovenci + so + se + jezili + da + ima + tako + zelo + neugledno + mesto + tam + v + + no + + + v + muzeju + + + potem + pa + ga + je + prestavil + eem + kancler + Hajder + enkrat + v + + ne + + + v + neko + + njiho + + + + p + + + + + vo + + + poli + + + na + vhod + politične + institucije + avstrijskega + nekega + glavarstva + + + kar + je + blo + seveda + strahotno + simbolno + dejanje + ne + da + ti + slovenski + knežji + kamen + v + neko + avstrijsko + vladno + institucijo + na + Koroškem + kjer + je + problem + dvojezičnosti + postaviš + kot + nek + avstrijski + simbol + + + eem + pač + za + recimo + za + za + nekatere + nesprejemljivo + + + no + potem + pa + je + bil + premaknjen + spet + nekam + drugam + + s + + + umaknjen + iz + take + eem + izzivalne + pozicije + tako + da + zdej + je + nekje + shranjen + na + Avstrijskem + Koroškem + + + medtem + ko + vojvodski + prestol + pa + stoji + a + ne + vsak + ga + lahko + vidi + ob + cesti + kekšnih + deset + kilometrov + severno + od + Celovca + na + Gosposvetskem + polju + + + lepo + ograjen + z + + o + + + z + železno + ograjo + morda + so + vas + že + kdaj + peljali + tja + + + ste + ga + že + videli + ? + + + + + + + + + + takole + zgleda + ne + + + eee + tud + za + tega + predvidevajo + da + je + bil + da + so + ga + sestavili + iz + enih + rimskih + ostankov + iz + enih + kamnitih + plošč + + + in + je + zanimivo + da + je + na + na + obe + strani + je + narejen + sedež + kar + se + tukaj + ne + vidi + + + eem + naj + bi + pa + to + mmm + + o + + + so + ga + uporabljali + odvisno + zdej + katerega + vojvodo + so + ustoličevali + + + enega + ki + je + vladal + bolj + na + vzhodu + al + drugega + bolj + na + zahodu + pač + na + tisto + stran + stola + se + je + moral + usest + + + + + + + + + + no + in + ta + prestol + eem + je + imel + vlogo + v + tretjem + delu + ustoličevanja + ne + to + se + pravi + da + je + to + ustoličevanje + imelo + več + faz + + + no + in + s + tega + prestola + je + potem + on + podelil + vazalom + fevde + zemljo + ta + novo + ustoličeni + vojvoda + + + + + + + + + + o + vprašanju + jezika + obreda + smo + pa + že + spregovorili + nekaj + besed + + + + + + + + + + eee + no + in + zdej + se + potem + premaknemo + počasi + + z + + + k + vojvodini + Koroški + smo + jo + že + omenili + + + postala + je + samostojna + vojvodina + znotraj + eee + Svetega + rimskega + cesarstva + in + je + dolgo + časa + ohranila + to + svojo + vojvodstvo + al + pa + deželnost + + + no + v + zdej + smo + že + v + srednjem + veku + a + ne + že + celo + v + + z + + + v + visokem + srednjem + veku + ko + se + je + začel + ko + se + je + utrdil + fevdalni + sistem + + + pomembne + plemiške + rodbine + so + se + naseljevale + na + tem + območju + kjer + živimo + + + in + takrat + najprej + so + začeli + nastajati + gradovi + + + gradovi + samostani + a + ne + iz + tistega + časa + eden + najstarejših + je + cistercijanski + samostan + Stična + + + ga + poznate + še + danes + delujoči + samostan + z + menihi + in + z + vsem + kar + zraven + spada + + + no + in + potem + naslednji + recimo + kartuzija + Žiče + ki + pa + danes + kot + tudi + veste + ni + več + delujoči + samostan + a + ne + so + samo + še + ruševine + + + ampak + take + zelo + impozantne + a + ne + zelo + primerno + za + kakšno + ekskurzijo + + + + + + + + + + eem + no + in + to + je + tudi + obdobje + ko + se + počasi + pač + na + tem + območju + začne + nemška + kolonizacija + ki + ima + potem + zelo + zelo + dolgo + zgodovino + + + + + + + + + + aha + tukile + se + še + enkrat + malo + ponovi + poglej + no + poglej + pozabla + zbrisat + + + + + + + + + + več + o + tem + da + se + + za + + + da + se + izoblikujejo + v + tem + času + tudi + dežele + bomo + govorili + takret + ko + bomo + imeli + temo + regionalna + razdelitev + + + ampak + to + je + čs + veste + da + ni + še + takret + govora + o + Sloveniji + al + pa + kej + podobnega + takret + govorimo + samo + o + deželah + a + ne + + + imamo + Štajersko + Koroško + Kranjsko + Goriško + potem + Istro + ki + se + sicer + ne + imenuje + kar + direktno + Istra + ampak + neka + Pazinska + nekej + tako + naprej + ampak + Istra + rečemo + zdej + mi + da + + z + + + da + bolj + vemo + o + čem + govorimo + in + pa + Trst + mesto + kot + posebna + enota + + + to + se + pravi + vse + te + dežele + so + bile + počasi + takrat + vklučene + potem + tudi + v + Sveto + rimsko + cesarstvo + + + + + + + + + + no + in + nastanek + mest + seveda + ravno + v + tem + obdobju + trgovskih + središč + in + samostanov + kot + smo + že + rekli + + + tole + morm + mal + popravt + preden + bom + dala + gor + + + ker + vidm + da + so + napake + + + + + + + + + + mal + zajamemo + sapo + a + ne + + + preden + se + premaknemo + spet + v + novo + ero + + + + + + + + + + eem + + + + + + + + + + začetek + Habsburžanov + ne + + + vemo + da + so + bli + Habsburžani + pač + ena + družina + plemiška + ki + je + pa + zacementirala + nemški + vpliv + na + današnem + slovenskem + prostoru + + + + + + + + + + začel + so + počasi + osvajati + dežele + in + tako + so + v + trinajstem + stoletju + so + že + posedovali + Avstrijo + ki + je + bla + prav + tako + takret + ena + izmed + dežel + a + ne + enako + ime + pač + kot + ima + danes + država + + + Avstrijo + in + Štajersko + najprej + potem + Koroško + Kranjsko + in + potem + + i + + + enako + v + štrnajstem + stoletju + še + Istro + in + Trst + + + to + se + pravi + vse + te + dežele + ki + so + ležale + na + današnjem + slovenskem + območju + so + prevzeli + Habsbužrani + + + tukajle + imam + nekej + v + oklepaju + nekej + kar + je + neodvisno + sicer + od + Habsburžanov + ampak + leta + tega + in + tega + kot + je + navedeno + je + bila + ustanovljena + dunajska + univerza + + + + + + + + + + za + nas + je + to + zelo + hudo + eee + pomembno + a + ne + ker + je + ta + univerza + prevzela + večino + študentov + ki + so + prihajali + s + slovenskega + območja + v + naslednjih + kolko + letih + ? + + + šeststo + ne + skoraj + šeststo + letih + dokler + ni + bla + ustanovljena + univerza + pri + nas + so + hodili + študirat + na + Dunaj + + + in + dokumentirano + naj + bi + bilo + pri + tistih + ki + so + to + raziskovali + da + je + že + v + prvem + stoletju + se + prav + prvih + sto + let + univerze + bilo + tam + sedemsto + študentov + za + katere + se + predvideva + da + so + bili + iz + slovenskih + dežel + da + so + bili + slovenskega + porekla + + + to + so + pregledali + evidence + to + se + pravi + ogromno + število + + + + + + + + + + a + ne + eee + v + nasprotju + s + tem + kar + smo + se + včasih + učil + da + so + bli + vsi + kmetje + pri + nas + da + so + bli + itak + sami + kmetje + + + očitno + že + takret + + t + + + v + štrnajstem + petnajstem + stoletju + ogromno + ljudi + šlo + študirat + na + univerzo + na + Dunaj + + + se + prav + zračunali + so + pač + po + nekih + dokumentih + predvidevajo + da + je + bilo + v + prvem + stoletju + sedemsto + takih + v + drugem + stoletju + pa + celo + tisoč + petsto + že + + + v + stotih + letih + ne + so + jih + našteli + toliko + + + + + + + + + + no + + + + + + + + + + eee + v + v + to + + ob + + + zdej + se + pa + že + vrnemo + nazaj + malo + iz + tega + ekskurza + univerzitetnega + nazaj + k + Habsburžanom + + + eem + v + prvi + polovici + jih + je + v + nekem + trenutku + začela + ogrožati + ena + domača + eem + plemiška + družina + to + so + bli + Celjski + grofje + za + katere + tud + vsi + dobro + veste + + + Celjski + grofje + so + mel + eno + tako + rcimo + stoletno + tradicijo + da + so + bli + res + močni + ne + in + da + so + se + v + nekem + trenutku + tud + začeli + s + Habsburžani + borit + za + za + neke + dežele + + + ampak + na + žalost + je + njim + pač + zagodla + jo + predvsem + v + eem + + + + + + + + + + njihova + pač + njihovo + potomstvo + a + ne + ko + je + se + zadnji + Celjan + Ulrik + tretji + ostal + brez + potomca + je + rodovina + takoj + propadla + + + ni + uspelo + pač + nardit + nekej + eee + kar + je + blo + pač + se + je + ustavilo + ne + tako + da + samo + dobrih + sto + let + je + trajalo + + + veste + pa + da + so + imeli + krasen + grad + nad + Celjem + a + ne + in + da + so + imeli + pač + neko + svojo + moč + tudi + vojaško + kar + je + blo + važno + in + zelo + bogato + plemiško + živlenje + + + + + + + + + + no + drugi + ki + so + bili + eee + drugi + kralj + a + ne + al + pa + drugo + ljudstvo + ki + je + tud + ogrožalo + v + enem + trenutku + Habsburžane + mal + kasneje + proti + koncu + petnajstega + stoletja + je + pa + bil + ogrski + kralj + Matija + Korvin + + + + + + + + + + za + ns + je + pač + pomemben + v + toliko + da + imamo + eno + bajko + ki + tega + Matijo + Korvina + kar + proglaša + za + slovenskega + kralja + in + to + Kralja + Matjaža + a + ne + + + ki + bo + prišel + in + bo + odrešil + Slovence + in + spi + pod + ne + vem + Peco + včasih + včasih + pod + Uršlo + goro + in + rešuje + + i + + + pač + ga + čakamo + da + nas + odreši + nemškega + vpliva + in + vseh + ostalih + težav + + + bil + pa + je + to + sicer + ogrski + kralj + ki + je + ravno + tako + eem + jih + začasno + premagal + ampak + takoj + po + njegovi + smrti + so + prevzeli + Habsburžani + vse + osvojene + dežele + nazaj + v + svoje + roke + in + potem + vladali + + + + + + + + + + no + eem + vodil + jih + je + takret + Maksimiljan + prvi + + + njega + omenjam + zato + ker + spet + po + nepotrjenih + zgodovinskih + virih + naj + bi + en + kranjski + al + pa + štajerski + no + Tomaž + Celjski + vsekakor + Tomaž + Celjski + naj + bi + napisal + rokopisno + knjigo + slovnico + iz + katere + je + učil + Maksimiljana + slovensko + + + žal + ni + nobenega + vira + dokumentiranega + ki + bi + to + nedvomno + potrdil + ampak + iz + pač + posrednih + virov + bi + to + lahko + bila + neka + prva + knjiga + ki + je + v + slovenščini + nastala + in + to + nej + bi + bil + celo + priročnik + za + učenje + slovenščine + za + tega + kralja + + + ki + pač + se + je + očitno + morda + zato + ker + je + vladal + tem + deželam + ali + pa + iz + kakšnega + drugega + razloga + ki + ga + ne + vemo + naj + bi + se + učil + slovensko + in + učil + nej + bi + ga + Tomaž + Celjski + + + + + + + + + + no + sicer + pa + je + to + že + konec + srednega + veka + in + so + petnajsto + in + šesnajsto + stoletje + pač + zaznamovali + kot + vsi + veste + turški + vpadi + kar + je + zelo + ogrožalo + vse + te + habsburške + dežele + + + in + da + bi + se + ubranili + pred + Turki + da + bi + nekako + strnili + vrste + so + imeli + pač + leta + tisoč + petsto + osnajst + v + Insbruku + nekakšen + deželni + zbor + vseh + dežel + + + eem + obljubljali + so + pomoč + pač + vojaške + vrste + se + strnejo + vendar + je + bilo + za + to + treba + podpisati + sporazum + o + tem + da + + s + + + vse + dežele + da + se + določi + dedna + celovitost + kot + se + temu + reče + + + torej + da + Habsburžani + vse + te + dežele + + de + + + dedujejo + naprej + + + in + tako + je + tudi + bilo + a + ne + + + zaradi + obrambe + pred + Turki + so + oni + prišli + do + vseh + teh + dežel + so + postali + za + dolgo + dolgo + stoletij + so + vse + to + + spreje + + + vladarji + tega + nekega + osrednega + evropskega + prostora + + + + + + + + + + eem + kaj + je + blo + potem + s + Habsburžani + naprej + kako + je + nastala + monarhija + in + tko + to + pa + potem + naslednjič + a + ne + + + + + + + + + + zej + nekoliko + se + za + konec + dotaknimo + še + kaj + je + bilo + z + jezikom + v + srednjem + veku + kaj + se + ve + kaj + je + dokumentirano + + + + + + + + + + celotno + izobraževanje + na + tem + ozemlju + je + blo + sprva + latinsko + + + + + + + + + + se + prav + to + obdobje + o + katerem + smo + danes + govoril + je + blo + latinsko + + + potem + kasneje + šele + po + letu + tisoč + tristo + se + je + v + skromnem + obsegu + začela + uveljavljati + nemščina + + + to + se + pravi + v + cerkvi + in + v + šolah + a + ne + sej + o + tem + govorimo + + + slovenščina + se + je + uporablala + predvsem + za + zasebno + rabo + jasno + tako + kot + že + vemo + med + kmečkim + prebivalstvom + vendar + zdej + novejše + raziskave + kažejo + da + tudi + v + mestih + pa + deloma + tudi + med + fevdalci + + +
+
+ + + no + začeli + bomo + kar + čisto + v + prazgodovini + a + ne + kaj + imamo + pri + nas + ohranjenega + iz + prazgodovine + + + jaz + sem + tisto + neandertalsko + piščalko + malo + izpustila + zaradi + tega + ker + stvari + niso + čisto + jasne + ne + + + če + ne + gre + to + slučajno + za + ene + + + + + + + + + + kosti + ki + so + bile + malo + preluknjane + pač + ni + dokazano + ali + je + bila + to + res + izdelana + piščalka + zato + začnemo + z + nečem + kar + je + sigurno + + + s + tole + vaško + situlo + ki + jo + vsi + poznate + in + ste + že + stokrat + + sti + + + slišali + da + je + + + rada + bi + samo + da + se + za + hip + zamislite + a + ne + da + to + sega + kako + daleč + nazaj + to + sega + + + peto + stoletje + pred + našim + štetjem + takrat + doba + ki + je + vladala + se + pač + zgodovinsko + obdobje + je + poimenovano + železna + doba + + + te + situle + so + bile + najdene + v + + bo + + + zelo + takih + bogatih + grobovih + + + to + se + pravi + sklepajo + da + so + tisti + bogatejši + ljudje + premožnejši + imeli + situle + in + so + jih + uporabljali + v + nekih + v + nekakšnih + obredih + in + so + z + njih + z + zajemalko + zajemali + pijačo + + + + + + + + + + eee + iz + tega + časa + so + ohranjena + še + razna + železna + orodja + tudi + pri + nas + grobišča + in + tudi + gradišča + tako + imenovana + na + hribih + + + zdaj + če + pogledate + še + bolj + natančno + ta + vzorec + na + vaški + situli + mogoče + tega + pa + res + niste + še + nikoli + pogledali + + + + + + + + + + bomo + videli + če + bo + to + potegnilo + ja + + + + + + + + + + vidite + lahko + da + je + zelo + zelo + natančno + vse + nekaj + izrisano + na + tej + vaški + situli + + + v + bistvu + so + tudi + situle + izrisane + iz + tega + sploh + sklepajo + kaj + je + to + + + tale + druga + vrsta + a + ne + kaže + na + to + kako + so + tale + sedi + in + ta + mu + iz + ene + posode + toči + pijačo + + + iz + tega + sklepajo + poglejte + kako + so + vsi + ti + ljudje + oblečeni + imajo + voz + se + pelje + na + vozu + ne + stol + ne + vem + kaj + vse + klobuk + konja + vpreženega + lepo + + + to + se + pravi + zdaj + pa + pomislite + pet + peto + stoletje + pred + našim + štetjem + to + je + res + daleč + nazaj + ne + tako + da + res + dragocena + najdba + + + tukajle + v + drugi + + vr + + + v + zadnji + vrsti + to + naj + bi + se + izmenjaval + kozorog + koza + kozorog + koza + in + tako + naprej + zadnji + je + pa + panter + + + in + tukajle + ima + pa + človeško + nogo + je + enega + pojedel + ne + + + + + + + + + + ta + slikica + se + ponovi + + + če + imate + potne + liste + predvidevam + da + ja + ne + jo + imate + celo + tole + to + je + ta + slika + ne + tukaj + se + začne + tukaj + se + nadaljuje + + + seveda + + o + + + očitno + imamo + to + za + enega + izmed + slovenskih + simbolov + + + samo + obrnjeni + so + malo + v + drugo + smer + pa + pomešani + so + + + + + + + + + + tukajle + en + sedi + pa + nogice + mu + dol + s + konja + bingljajo + + + + + + + + + + tako + da + izjemno + + i + + + dodelana + ta + slika + + + to + seveda + nima + še + zveze + s + Slovenci + a + ne + takrat + so + živeli + na + tem + območju + tako + imenovani + Veneti + + + ampak + najdeno + je + to + pri + Vačah + torej + na + našem + kulturnem + prostoru + in + lahko + vidimo + kako + daleč + nazaj + sežejo + prvi + prebivalci + + + + + + + + + + tako + no + ta + to + je + vaška + situla + torej + nekakšno + vedro + za + iz + katerega + se + pije + vedro + ki + govori + samo + o + sebi + a + ne + + + če + ne + bi + bilo + tako + natančno + izdelane + te + slike + verjetno + tudi + ne + bi + vedeli + za + kaj + se + je + uporabljalo + + nata + + + v + bistvu + se + iz + tega + prepozna + + + + + + + + + + in + potem + zdaj + že + mi + naredimo + strašen + preskok + par + stoletij + + + veste + da + so + bili + tudi + Kelti + in + Rimljani + na + našem + območju + + + zdaj + čisto + na + kratko + samo + toliko + kolikor + se + spodobi + za + enega + izobraženca + + + v + kar + pravkar + se + razvijate + a + ne + da + se + ve + pač + da + so + bili + na + našem + ozemlju + so + bila + plemena + Keltov + + + zdaj + kdo + so + Kelti + v + to + se + ne + bomo + spuščali + ampak + nekako + tako + se + naj + bi + bili + neki + predniki + se + pravi + to + kar + se + je + iz + Keltov + razvilo + zdaj + živi + na + Irskem + recimo + a + ne + tako + pa + na + Škotskem + tako + zelo + posplošeno + povedano + + + no + potem + kar + je + bolj + važno + za + naše + obdobje + pa + so + že + počasi + začeli + prihajati + k + nam + Rimljani + a + ne + vdor + rimskih + plemen + + + in + to + se + je + začelo + kot + vidite + glejte + približno + v + drugem + stoletju + pred + našim + štetjem + + + prvo + mesto + tako + je + bila + Aquilea + ali + Oglej + + + prvo + rimsko + mesto + na + slovenskem + ozemlju + Aquilea + Oglej + + + kasneje + v + zgodovini + veste + da + je + to + mesto + odigralo + veliko + vlogo + kot + neko + središče + krščansko + a + ne + oglejski + patriarh + + + ampak + k + temu + se + vrnemo + kasneje + + + bilo + je + pa + prvo + rimljansko + mesto + + + a + veste + kje + je + Oglej + ? + + + + + + + + + + ja + kje + ? + + + + + + + + + + v + Italiji + ? + + + ja + no + pri + približno + pri + izviru + Soče + a + ne + + + eem + tam + je + zelo + tja + je + zelo + lep + izlet + zelo + lep + sprehod + + + se + vidijo + ti + + ro + + + rimski + ostanki + so + veliki + stebri + so + ohranjeni + zelo + lepo + je + in + drevored + in + tako + + + če + boste + kdaj + po + tistih + koncih + hodili + je + lep + izlet + + + no + potem + cesar + Oktavijan + recimo + je + + o + + + pač + nadaljeval + s + tem + rimskim + osvajanjem + premaknil + mejo + nekje + do + Donave + Rimskega + cesarstva + + + in + v + tistem + času + to + se + pravi + malo + pred + našim + štetjem + pa + okrog + ničle + pa + naprej + so + nastala + rimska + mesta + na + našem + področju + Emona + Celeia + Petovio + vsi + poznamo + a + ne + + + no + in + + na + + + narejen + je + bil + cestni + sistem + s + to + glavno + osjo + kot + vidite + zapisano + do + Karuntuma + + + to + je + bilo + pa + eno + mesto + ob + Donavi + ki + je + danes + nekje + na + polovici + poti + med + Dunajem + in + Bratislavo + + + to + se + pravi + ta + cestna + povezava + je + šla + od + morja + od + Jadranskega + morja + praktično + do + tam + kjer + je + današnji + Dunaj + prva + cesta + + + + + + + + + + eee + kaj + se + je + v + rimskih + časih + dogajalo + tukaj + se + s + tem + se + ne + bomo + ukvarjali + ostanki + so + veste + da + v + Ljubljani + zelo + velik + rimski + zid + lepo + ohranjen + + + zdaj + ne + morejo + zgraditi + univerzitetne + knjižnice + ker + je + preveč + rimskih + ostankov + in + tako + naprej + + + no + ampak + že + v + petem + in + šestem + stoletju + je + začela + rimska + oblast + slabeti + + + najprej + zaradi + vdorov + germanskih + plemen + s + severa + so + pritisnili + navzdol + in + tako + se + je + pač + to + rimsko + obdobje + pri + nas + kar + hitro + končalo + to + se + pravi + vidite + šeststo + sedemsto + let + nekaj + takega + da + so + bili + pri + nas + Rimljani + + + in + začelo + se + je + v + šestem + stoletju + seveda + naseljevanje + + + + + + + + + + Slovanov + a + ne + + + šele + sedaj + pridejo + naši + predniki + na + to + območje + + + + + + + + + + to + tega + se + verjetno + vsega + spominjate + počasi + še + iz + srednje + šole + pač + naselitev + Slovanov + v + dveh + v + dveh + nekako + v + dveh + valovih + in + tudi + v + dveh + časovnih + zaporedjih + + + eni + so + šli + bolj + k + Alpam + a + ne + to + so + bili + recimo + naši + predniki + eni + so + šli + pa + bolj + na + moravsko + stran + v + Panonijo + + + + + + + + + + eee + to + niti + ni + tako + pomembno + najprej + niso + bili + samostojni + a + ne + so + bili + pod + eno + oblastjo + Avarov + + + Avari + so + bili + pa + spet + eno + drugo + ljudstvo + ki + so + se + istočasno + priseljevali + na + to + področje + + + ampak + v + začetku + sedmega + stoletja + so + pa + + z + + + že + začele + nastajati + neke + samostojne + plemenske + zveze + + + verjetno + se + iz + šole + spomnite + neke + Samove + plemenske + zveze + ampak + zdaj + ta + trenutek + to + pustimo + eee + na + mmm + pač + mmm + ob + strani + + + ampak + začele + so + se + neke + tvorbe + ki + so + pripeljale + do + prve + slovenske + države + + + + + + + + + + ki + je + pa + bila + + + + + + + + + + ne + države + ne + smemo + reči + ne + neke + samostojne + tvorbe + podobne + državi + ki + se + ji + je + reklo + Karantanija + + + + + + + + + + Karantanija + + + + + + + + + + to + se + pravi + za + za + Karantanijo + važno + da + si + zapomnite + da + je + bila + bila + tvorba + ki + + ne + + + bi + nastala + nekje + v + sedmem + stoletju + + + veste + da + so + zapiski + ali + pa + dokumenti + o + teh + prazgodovinskih + praktično + stvareh + se + eem + slabo + ohranjeni + ne + iz + starega + veka + + + ampak + toliko + se + že + da + sklepati + da + pač + približno + se + ve + da + je + ta + Karantanija + bila + + + + da + je + bila + na + začetku + popolnoma + neodvisna + država + + + vendar + to + je + bilo + samo + kakšnih + eem + mislim + da + okrog + sto + let + je + bila + neodvisna + + + potem + so + pa + že + prišli + pod + vpliv + Bavarcev + + + ampak + še + kljub + temu + se + govori + da + je + Karantanija + obstajala + tristo + let + + + prvih + sto + let + kot + neodvisna + država + drugih + dvesto + let + pa + kot + neka + tvorba + + sa + + + mmm + z + relativno + samostojnostjo + pod + Bavarci + in + še + kasneje + v + Frankovski + državi + + + to + se + pravi + ni + bila + ves + čas + samostojna + samo + na + začetku + + + takrat + ko + so + Bavarce + prosili + za + neko + pomoč + v + vojnah + so + pač + postali + eem + podložni + njim + + + no + tukaj + se + mi + zdi + en + zanimiv + detajl + + + + + + + + + + eem + torej + kako + so + se + s + temi + Bavarci + dogovorili + ne + + + da + so + jim + pomagali + v + eni + borbi + z + Avari + so + jim + poslali + so + jim + morali + poslati + dva + talca + + + to + sta + bila + bratranca + a + ne + Gorazd + in + Hotimir + + + Gorazd + je + bil + + s + + + + vla + + + eee + knezov + sin + Hotimir + je + bil + pa + njegov + bratranec + torej + + + in + ta + dva + so + potem + Bavarci + pokristjanili + + + zdaj + Gorazd + ki + je + bil + pač + dedni + naslednik + je + vladal + samo + tri + leta + in + so + ga + ubili + + + in + tako + je + potem + njegov + bratranec + dejansko + prišel + na + oblast + Hotimir + + + in + v + času + Hotimira + torej + v + Karantaniji + se + je + začelo + pri + nas + pokristjanjevanje + + + temle + zgoraj + me + precej + motite + dekleta + če + ne + zamerite + + + zdaj + ali + boste + nehale + klepetati + ali + pa + vas + prosim + če + zapustite + prizorišče + ne + + + v + redu + kakor + vam + je + ljubše + + + + + + + + + + prosim + ? + + + no + kaj + boste + izbrale + ? + + + + + + + + + + ne + vem + kaj + to + pomeni + + + aha + dobro + + + v + redu + no + ustavili + smo + se + pri + Hotimirju + + + + eee + ki + je + prevzel + oblast + v + Karantaniji + + + in + od + kod + ga + poznamo + od + kod + mi + Hotimira + poznamo + ? + + + + + + + + + + iz + Krsta + seveda + ne + v + Krstu + obravnava + pač + vsebina + tema + Krsta + je + pokristjanjevanje + in + kot + vidite + tudi + tukaj + in + so + navedeni + trije + upori + seveda + so + se + prebivalci + upirali + pokristjanjevanju + + + eem + ni + šlo + tako + zlahka + ampak + Hotimir + je + bil + tisti + ki + je + pri + tem + vztrajal + + + ker + je + moral + vztrajati + zato + ker + je + bil + predan + za + talca + Bavarcem + in + je + pač + moral + potem + ubogati + kar + so + mu + naročili + + + no + zdaj + samo + še + za + eno + orientacijo + + + mmm + to + verjetno + tudi + vsi + se + še + spomnite + + + kje + je + Karantanija + ležala + + + to + seveda + ni + bilo + na + prav + na + območju + Slovenije + današnje + ampak + je + bilo + severno + a + ne + na + območju + današnje + avstrijske + Koroške + in + še + bolj + gor + na + sever + + + + + + + + + + tako + naša + pradomovina + v + nekem + smislu + + + + + + + + + + no + eem + + + + + + + + + + mogoče + malo + preveč + hitim + + + + + + + + + + kot + sem + že + prej + povedala + je + Karantanija + zelo + hitro + izgubila + svoje + samostojnost + + + + + + + + + + in + prišla + pod + eee + bila + vključena + tudi + potem + najprej + pod + bavarskega + kneza + potem + ko + so + pa + Bavarci + izgubili + so + pa + še + prišli + v + Frankovsko + državo + + + + + + + + + + tam + se + je + potem + vse + reorganiziralo + ampak + Karantanija + je + ohranila + neko + plemensko + notranjo + + u + + + ureditev + tako + da + je + na + neki + način + obstala + še + nekaj + stoletij + + + kar + je + najbolj + znano + iz + tega + časa + je + obred + ustoličevanja + koroških + vojvod + a + ne + + + eee + ki + se + je + potem + ohranil + ker + dejansko + potem + vsaj + v + desetem + stoletju + tam + devetsto + petdeset + potem + Karantanije + dejansko + ni + bilo + več + niti + v + okviru + Frankovske + države + + + ampak + ta + obred + ustoličevanja + se + je + pa + ohranil + še + petsto + let + + + bili + so + tam + eem + že + čisto + drugi + gospodarji + ampak + nekako + je + ta + tradicija + ostala + a + ne + kar + je + zelo + nenavadno + + + in + je + v + večih + knjigah + tujih + seveda + ta + obred + popisan + in + dokumentiran + + + zdaj + kaj + točno + se + je + tam + dogajalo + + + se + pravi + najprej + je + šlo + za + ustoličevanje + karantanskih + knezov + + + Karantanija + je + bila + kneževina + so + imeli + kneze + a + ne + + + pač + prvo + prvi + del + prvo + kar + poznamo + je + bilo + ustoličevanje + na + knežjem + kamnu + + + zdaj + če + + z + + + če + pogledamo + kar + hitro + sliko + da + bomo + vedeli + o + čem + govorimo + + + + + + + + + + tole + je + bil + ta + knežji + kamen + ne + + + v + resnici + je + to + kot + vidite + jasno + je + eee + zgornji + del + enega + rimskega + stebra + + + ki + je + bil + prinešen + seveda + za + njih + + s + + + je + + se + + + so + bili + rimski + časi + že + ravno + tako + arhaični + kot + so + danes + za + nas + + + ne + toliko + ampak + bilo + je + to + nekaj + kar + je + bilo + tisoč + let + staro + že + takrat + ne + + + in + to + je + bilo + z + enega + bližnjega + mesta + eee + rimske + ostaline + so + ta + kamen + prinesli + na + Krnski + grad + + + + predvid + + + predvidoma + je + bilo + to + najprej + na + Krnskem + gradu + + + in + so + potem + začeli + tukaj + to + ustoličevanje + knezov + + + zdaj + to + je + bilo + to + je + imelo + simboličen + pomen + a + ne + + + eem + knez + naj + bi + tukaj + vladar + Karantancev + je + na + tem + + presto + + + recimo + no + kamnu + pač + sprejel + oblast + iz + rok + ljudstva + + + + + + + + + + kako + + j + + + kaj + kakšen + pomen + je + imelo + to + prvotno + + n + + + ni + čisto + jasno + + + ampak + ve + se + da + tudi + kasneje + ko + je + bila + oblast + že + dedna + prvotno + ni + bila + dedna + ampak + tudi + ko + je + postala + oblast + dedna + še + vedno + ker + jasno + je + bilo + da + bo + sin + nasledil + očeta + + + ampak + ko + se + je + to + zgodilo + še + vedno + je + simbolično + šel + sedet + na + ta + knežji + kamen + in + je + sprejel + pač + eee + voljo + ljudstva + da + jim + bo + da + ga + postavljajo + za + kneza + in + on + jim + je + potem + obljubil + da + bo + dobro + vladal + + + zdaj + jasno + ključno + temeljno + vprašanje + v + kakšnem + jeziku + je + to + potekalo + a + ne + se + na + žalost + ne + ve + zaradi + tega + ker + ni + ohranjenih + zapisov + + + zdaj + mi + z + veseljem + sklepamo + in + si + želimo + da + je + bilo + to + v + nekem + slovenskem + arhaičnem + jeziku + predvidoma + ja + ker + se + je + začelo + v + Karantaniji + + + in + + p + + + to + je + potem + možno + da + tudi + še + potem + ko + so + koroške + vojvode + ki + niso + bili + več + nujno + slovenskega + izvora + ali + to + kar + razumemo + za + slovensko + da + so + da + je + + tak + + + tudi + še + takrat + potekal + obred + ustoličevanja + v + slovenščini + + + to + bi + pomenilo + da + so + oni + v + tujem + jeziku + govorili + da + je + bila + slovenščina + kot + tuji + jezik + neki + obredni + jezik + ustoličevanja + kar + je + dokaj + nenavadno + ampak + žal + zdaj + teh + ni + ohranjenih + eee + + natančnih + zapisov + ki + bi + to + dokumentirali + + + no + ta + knežji + kamen + se + je + seveda + tudi + pojavil + zdaj + kot + slovenski + nacionalni + simbol + na + kovancu + našem + + + a + veste + na + katerem + ? + + + ja + vse + to + pa + mmm + to + se + pa + dobro + spoznate + + + + + + + + + + + no + potem + pa + je + tukaj + še + vojvodski + prestol + a + ne + ki + je + pa + nekaj + drugega + + + aha + zdaj + je + ta + + ki + + + kje + je + zdaj + knežji + kamen + + + dolgo + je + bil + v + muzeju + nekje + v + Celovcu + Slovenci + so + se + jezili + da + ima + tako + zelo + neugledno + mesto + tam + v + + no + + + v + muzeju + + + potem + pa + ga + je + prestavil + eem + kancler + Heider + enkrat + v + + ne + + + v + neko + + njiho + + + + p + + + + + vo + + + poli + + + na + vhod + politične + institucije + avstrijskega + nekega + glavarstva + + + kar + je + bilo + seveda + strahotno + simbolno + dejanje + ne + da + ti + slovenski + knežji + kamen + v + neko + avstrijsko + vladno + institucijo + na + Koroškem + kjer + je + problem + dvojezičnosti + postaviš + kot + neki + avstrijski + simbol + + + eem + pač + za + recimo + za + za + nekatere + nesprejemljivo + + + no + potem + pa + je + bil + premaknjen + spet + nekam + drugam + + s + + + umaknjen + iz + take + eem + izzivalne + pozicije + tako + da + zdaj + je + nekje + shranjen + na + Avstrijskem + Koroškem + + + medtem + ko + vojvodski + prestol + pa + stoji + a + ne + vsak + ga + lahko + vidi + ob + cesti + kakšnih + deset + kilometrov + severno + od + Celovca + na + Gosposvetskem + polju + + + lepo + ograjen + z + + o + + + z + železno + ograjo + morda + so + vas + že + kdaj + peljali + tja + + + ste + ga + že + videli + ? + + + + + + + + + + takole + izgleda + ne + + + eee + tudi + za + tega + predvidevajo + da + je + bil + da + so + ga + sestavili + iz + enih + rimskih + ostankov + iz + enih + kamnitih + plošč + + + in + je + zanimivo + da + je + na + na + obe + strani + je + narejen + sedež + kar + se + tukaj + ne + vidi + + + eem + naj + bi + pa + to + mmm + + o + + + so + ga + uporabljali + odvisno + zdaj + katerega + vojvodo + so + ustoličevali + + + enega + ki + je + vladal + bolj + na + vzhodu + ali + drugega + bolj + na + zahodu + pač + na + tisto + stran + stola + se + je + moral + usesti + + + + + + + + + + no + in + ta + prestol + eem + je + imel + vlogo + v + tretjem + delu + ustoličevanja + ne + to + se + pravi + da + je + to + ustoličevanje + imelo + več + faz + + + no + in + s + tega + prestola + je + potem + on + podelil + vazalom + fevde + zemljo + ta + novo + ustoličeni + vojvoda + + + + + + + + + + o + vprašanju + jezika + obreda + smo + pa + že + spregovorili + nekaj + besed + + + + + + + + + + eee + no + in + zdaj + se + potem + premaknemo + počasi + + z + + + k + vojvodini + Koroški + smo + jo + že + omenili + + + postala + je + samostojna + vojvodina + znotraj + eee + Svetega + rimskega + cesarstva + in + je + dolgo + časa + ohranila + to + svojo + vojvodstvo + ali + pa + deželnost + + + no + v + zdaj + smo + že + v + srednjem + veku + a + ne + že + celo + v + + z + + + v + visokem + srednjem + veku + ko + se + je + začel + ko + se + je + utrdil + fevdalni + sistem + + + pomembne + plemiške + rodbine + so + se + naseljevale + na + tem + območju + kjer + živimo + + + in + takrat + najprej + so + začeli + nastajati + gradovi + + + gradovi + samostani + a + ne + iz + tistega + časa + eden + najstarejših + je + cistercijanski + samostan + Stična + + + ga + poznate + še + danes + delujoči + samostan + z + menihi + in + z + vsem + kar + zraven + spada + + + no + in + potem + naslednji + recimo + kartuzija + Žiče + ki + pa + danes + kot + tudi + veste + ni + več + delujoči + samostan + a + ne + so + samo + še + ruševine + + + ampak + take + zelo + impozantne + a + ne + zelo + primerno + za + kakšno + ekskurzijo + + + + + + + + + + eem + no + in + to + je + tudi + obdobje + ko + se + počasi + pač + na + tem + območju + začne + nemška + kolonizacija + ki + ima + potem + zelo + zelo + dolgo + zgodovino + + + + + + + + + + aha + tukajle + se + še + enkrat + malo + ponovi + poglej + no + poglej + pozabila + zbrisati + + + + + + + + + + več + o + tem + da + se + + za + + + da + se + izoblikujejo + v + tem + času + tudi + dežele + bomo + govorili + takrat + ko + bomo + imeli + temo + regionalna + razdelitev + + + ampak + to + je + čas + veste + da + ni + še + takrat + govora + o + Sloveniji + ali + pa + kaj + podobnega + takrat + govorimo + samo + o + deželah + a + ne + + + imamo + Štajersko + Koroško + Kranjsko + Goriško + potem + Istro + ki + se + sicer + ne + imenuje + kar + direktno + Istra + ampak + neka + Pazinska + nekaj + tako + naprej + ampak + Istra + rečemo + zdaj + mi + da + + z + + + da + bolj + vemo + o + čem + govorimo + in + pa + Trst + mesto + kot + posebna + enota + + + to + se + pravi + vse + te + dežele + so + bile + počasi + takrat + vključene + potem + tudi + v + Sveto + rimsko + cesarstvo + + + + + + + + + + no + in + nastanek + mest + seveda + ravno + v + tem + obdobju + trgovskih + središč + in + samostanov + kot + smo + že + rekli + + + tole + moram + malo + popraviti + preden + bom + dala + gor + + + ker + vidim + da + so + napake + + + + + + + + + + malo + zajamemo + sapo + a + ne + + + preden + se + premaknemo + spet + v + novo + ero + + + + + + + + + + eem + + + + + + + + + + začetek + Habsburžanov + ne + + + vemo + da + so + bili + Habsburžani + pač + ena + družina + plemiška + ki + je + pa + zacementirala + nemški + vpliv + na + današnjem + slovenskem + prostoru + + + + + + + + + + začeli + so + počasi + osvajati + dežele + in + tako + so + v + trinajstem + stoletju + so + že + posedovali + Avstrijo + ki + je + bila + prav + tako + takrat + ena + izmed + dežel + a + ne + enako + ime + pač + kot + ima + danes + država + + + Avstrijo + in + Štajersko + najprej + potem + Koroško + Kranjsko + in + potem + + i + + + enako + v + štirinajstem + stoletju + še + Istro + in + Trst + + + to + se + pravi + vse + te + dežele + ki + so + ležale + na + današnjem + slovenskem + območju + so + prevzeli + Habsburžani + + + tukajle + imam + nekaj + v + oklepaju + nekaj + kar + je + neodvisno + sicer + od + Habsburžanov + ampak + leta + tega + in + tega + kot + je + navedeno + je + bila + ustanovljena + dunajska + univerza + + + + + + + + + + za + nas + je + to + zelo + hudo + eee + pomembno + a + ne + ker + je + ta + univerza + prevzela + večino + študentov + ki + so + prihajali + s + slovenskega + območja + v + naslednjih + koliko + letih + ? + + + šeststo + ne + skoraj + šeststo + letih + dokler + ni + bila + ustanovljena + univerza + pri + nas + so + hodili + študirat + na + Dunaj + + + in + dokumentirano + naj + bi + bilo + pri + tistih + ki + so + to + raziskovali + da + je + že + v + prvem + stoletju + se + pravi + prvih + sto + let + univerze + bilo + tam + sedemsto + študentov + za + katere + se + predvideva + da + so + bili + iz + slovenskih + dežel + da + so + bili + slovenskega + porekla + + + to + so + pregledali + evidence + to + se + pravi + ogromno + število + + + + + + + + + + a + ne + eee + v + nasprotju + s + tem + kar + smo + se + včasih + učili + da + so + bili + vsi + kmetje + pri + nas + da + so + bili + itak + sami + kmetje + + + očitno + že + takrat + + t + + + v + štirinajstem + petnajstem + stoletju + ogromno + ljudi + šlo + študirat + na + univerzo + na + Dunaj + + + se + pravi + izračunali + so + pač + po + nekih + dokumentih + predvidevajo + da + je + bilo + v + prvem + stoletju + sedemsto + takih + v + drugem + stoletju + pa + celo + tisoč + petsto + že + + + v + stotih + letih + ne + so + jih + našteli + toliko + + + + + + + + + + no + + + + + + + + + + eee + v + v + to + + ob + + + zdaj + se + pa + že + vrnemo + nazaj + malo + iz + tega + ekskurza + univerzitetnega + nazaj + k + Habsburžanom + + + eem + v + prvi + polovici + jih + je + v + nekem + trenutku + začela + ogrožati + ena + domača + eem + plemiška + družina + to + so + bili + Celjski + grofje + za + katere + tudi + vsi + dobro + veste + + + Celjski + grofje + so + imeli + eno + tako + recimo + stoletno + tradicijo + da + so + bili + res + močni + ne + in + da + so + se + v + nekem + trenutku + tudi + začeli + s + Habsburžani + boriti + za + za + neke + dežele + + + ampak + na + žalost + je + njim + pač + zagodla + jo + predvsem + v + eem + + + + + + + + + + njihova + pač + njihovo + potomstvo + a + ne + ko + je + se + zadnji + Celjan + Ulrik + tretji + ostal + brez + potomca + je + rodovina + takoj + propadla + + + ni + uspelo + pač + narediti + nekaj + eee + kar + je + bilo + pač + se + je + ustavilo + ne + tako + da + samo + dobrih + sto + let + je + trajalo + + + veste + pa + da + so + imeli + krasen + grad + nad + Celjem + a + ne + in + da + so + imeli + pač + neko + svojo + moč + tudi + vojaško + kar + je + bilo + važno + in + zelo + bogato + plemiško + življenje + + + + + + + + + + no + drugi + ki + so + bili + eee + drugi + kralj + a + ne + ali + pa + drugo + ljudstvo + ki + je + tudi + ogrožalo + v + enem + trenutku + Habsburžane + malo + kasneje + proti + koncu + petnajstega + stoletja + je + pa + bil + ogrski + kralj + Matija + Korvin + + + + + + + + + + za + nas + je + pač + pomemben + v + toliko + da + imamo + eno + bajko + ki + tega + Matijo + Korvina + kar + proglaša + za + slovenskega + kralja + in + to + Kralja + Matjaža + a + ne + + + ki + bo + prišel + in + bo + odrešil + Slovence + in + spi + pod + ne + vem + Peco + včasih + včasih + pod + Uršlo + goro + in + rešuje + + i + + + pač + ga + čakamo + da + nas + odreši + nemškega + vpliva + in + vseh + ostalih + težav + + + bil + pa + je + to + sicer + ogrski + kralj + ki + je + ravno + tako + eem + jih + začasno + premagal + ampak + takoj + po + njegovi + smrti + so + prevzeli + Habsburžani + vse + osvojene + dežele + nazaj + v + svoje + roke + in + potem + vladali + + + + + + + + + + no + eem + vodil + jih + je + takrat + Maksimiljan + prvi + + + njega + omenjam + zato + ker + spet + po + nepotrjenih + zgodovinskih + virih + naj + bi + en + kranjski + ali + pa + štajerski + no + Tomaž + Celjski + vsekakor + Tomaž + Celjski + naj + bi + napisal + rokopisno + knjigo + slovnico + iz + katere + je + učil + Maksimiljana + slovensko + + + žal + ni + nobenega + vira + dokumentiranega + ki + bi + to + nedvomno + potrdil + ampak + iz + pač + posrednih + virov + bi + to + lahko + bila + neka + prva + knjiga + ki + je + v + slovenščini + nastala + in + to + naj + bi + bil + celo + priročnik + za + učenje + slovenščine + za + tega + kralja + + + ki + pač + se + je + očitno + morda + zato + ker + je + vladal + tem + deželam + ali + pa + iz + kakšnega + drugega + razloga + ki + ga + ne + vemo + naj + bi + se + učil + slovensko + in + učil + naj + bi + ga + Tomaž + Celjski + + + + + + + + + + no + sicer + pa + je + to + že + konec + srednjega + veka + in + so + petnajsto + in + šestnajsto + stoletje + pač + zaznamovali + kot + vsi + veste + turški + vpadi + kar + je + zelo + ogrožalo + vse + te + habsburške + dežele + + + in + da + bi + se + ubranili + pred + Turki + da + bi + nekako + strnili + vrste + so + imeli + pač + leta + tisoč + petsto + osemnajst + v + Innsbrucku + nekakšen + deželni + zbor + vseh + dežel + + + eem + obljubljali + so + pomoč + pač + vojaške + vrste + se + strnejo + vendar + je + bilo + za + to + treba + podpisati + sporazum + o + tem + da + + s + + + vse + dežele + da + se + določi + dedna + celovitost + kot + se + temu + reče + + + torej + da + Habsburžani + vse + te + dežele + + da + + + dedujejo + naprej + + + in + tako + je + tudi + bilo + a + ne + + + zaradi + obrambe + pred + Turki + so + oni + prišli + do + vseh + teh + dežel + so + postali + za + dolgo + dolgo + stoletij + so + vse + to + + spreje + + + vladarji + tega + nekega + osrednjega + evropskega + prostora + + + + + + + + + + eem + kaj + je + bilo + potem + s + Habsburžani + naprej + kako + je + nastala + monarhija + in + tako + to + pa + potem + naslednjič + a + ne + + + + + + + + + + zdaj + nekoliko + se + za + konec + dotaknimo + še + kaj + je + bilo + z + jezikom + v + srednjem + veku + kaj + se + ve + kaj + je + dokumentirano + + + + + + + + + + celotno + izobraževanje + na + tem + ozemlju + je + bilo + sprva + latinsko + + + + + + + + + + se + pravi + to + obdobje + o + katerem + smo + danes + govorili + je + bilo + latinsko + + + potem + kasneje + šele + po + letu + tisoč + tristo + se + je + v + skromnem + obsegu + začela + uveljavljati + nemščina + + + to + se + pravi + v + cerkvi + in + v + šolah + a + ne + saj + o + tem + govorimo + + + slovenščina + se + je + uporabljala + predvsem + za + zasebno + rabo + jasno + tako + kot + že + vemo + med + kmečkim + prebivalstvom + vendar + zdaj + novejše + raziskave + kažejo + da + tudi + v + mestih + pa + deloma + tudi + med + fevdalci + + +
+ +
+
+ + + + + + Ura filozofije, pri kateri predavatelj študentom razlaga nemško klasično filozofijo. + + snemanje + Neža Pahovnik + + + transkripcija + Alenka Mirkac + + + + 2010-03-12 + Ljubljana + + + + + + + terenski posnetek + + + 2010-03-12 + + + + + + + + + + + + + + akademski, humanistika + + + + + + + + + moški + + LJ, NM + fakulteta ali več + + + + + + + + + LJ + Ljubljana + + + 2010-01-06 + + + + + + + +
+ + + ostali + smo + pri + paragrafu + osenoseneset + ne + ? + + + če + tako + vprašam + takoj + ste + prebrali + ? + + + je + kakšno + vprašanje + ? + + + + + + + + + + eee + je + kakšno + vprašanje + ki + je + ostalo + od + zadnjič + ? + + + je + kaj + nejasnega + v + tem + naslednjem + ali + sejnoseneset + ali + v + sedeminosemdesetem + ali + osenosnsetem + paragrafu + ? + + + + + + + + + + ne + ? + + + + + + + + + + eee + dobro + gremo + potem + ponovimo + do + kod + smo + prišli + + + + + + + + + + eee + + + + + + + + + + tako + skratka + uvod + eee + rekli + smo + da + se + vse + skupaj + + o + + + eee + dogaja + na + način + preizkusa + realnosti + vednosti + + + eee + če + preskočimo + vse + ostalo + + m + + + eee + mamo + neko + pozicijo + naravne + zavesti + ločujemo + eee + moment + vednosti + moment + resnice + eee + identitete + razlike + + + eee + in + sedaj + vse + skupaj + bo + potekalo + na + na + način + imanentnega + preizkušanja + koliko + se + vednost + in + predmet + ujemata + koliko + vednost + in + nasebje + sovpadata + + + zastavlja + se + najprej + vprašanje + kje + bomo + dobili + kriterij + tega + preizkusa + preizkusa + realnosti + vednosti + + + spomnite + smo + rekli + eee + zavest + eee + pod + pojem + vednosti + ta + kriterij + je + vedno + znova + postavlja + + sama + eee + na + podlagi + tistega + kar + sama + razglasša + za + resnično + bomo + imeli + eee + kriterij + da + merimo + njeno + vednost + po + njem + a + ne + + + to + je + eno + in + drugo + eee + kako + se + izvaja + ta + preizkus + ? + + + rekli + smo + tudi + da + ne + samo + da + naravna + zavest + prinaša + sama + kriterij + preizkusa + temveč + tudi + sama + izvede + ta + preizkus + ker + hoče + da + bi + bila + njena + vednost + realna + vednost + vednost + nasebja + + + kar + ostane + nam + je + potemtakem + samo + to + ne + samo + da + ostane + nam + samo + opazovanje + + das + rajne + cu + zeen + + ampak + je + to + eee + eee + čista + pasivnost + + + nevmešavanje + v + potek + dogajanja + v + potek + preizkusa + pozitivna + zahteva + kajti + edino + na + ta + način + lahko + zagotovimo + da + je + preizkus + res + imanenten + veljaven + za + naravno + zavest + eee + samo + + + eee + videli + smo + zastavili + smo + si + tedaj + tudi + vprašanje + eee + kako + je + pa + mogoče + opazovanje + preizkusa + vednosti + druge + naravne + zavesti + ne + ? + + + druge + zavesti + rekli + smo + jasno + je + da + eee + četudi + se + zdi + najprej + da + ona + postavlja + kriterij + ona + izvaja + preizkus + mi + je + zgolj + opazujemo + smo + nazadnje + lahko + samo + mi + tisti + ki + izvajamo + ta + preizkus + in + sami + sebe + opazujemo + kot + eee + izvajalce + tega + preizkusa + + + ampak + zadnjič + smo + se + eee + zaustavili + pri + vprašanju + dobro + seveda + če + si + vednost + in + predmet + ujemata + smo + prišli + do + pozicije + ko + vednost + ve + da + ve + + + kot + naravna + zavest + ko + zavest + ve + da + ve + in + to + je + točka + kjer + se + lahko + potem + naprej + nadaljuje + znanost + oziroma + kjer + se + lahko + šele + zares + začne + znanost + sama + znanost + logike + + + če + se + pa + eee + vednost + in + predmet + ne + ujemata + smo + videli + kaj + se + tedaj + eee + zgodi + + + zgodi + se + to + da + se + eee + zdi + da + se + mora + vednost + prilagoditi + predmetu + ampak + s + spremembo + + pr + + + eee + vednosti + + s + + + se + spremeni + tudi + predmet + kajti + vednost + je + bila + bistveno + vednost + tega + predmeta + in + predmet + je + bil + bistveno + vezan + na + to + vednost + + + in + eee + tako + da + preizkus + vednosti + ni + samo + preizkus + vednosti + ampak + hkrati + tudi + preizkus + predmeta + tako + da + če + vednost + ne + vzdrži + tudi + kriterij + eee + pade + skratka + vse + se + sprevrže + v + eee + vse + se + + sprev + + + zaide + v + eee + gibanje + + + to + nekako + poznamo + ampak + vprašanje + je + bilo + kako + lahko + sploh + pride + do + neujemanja + med + vednostjo + in + predmetom + ko + pa + sta + vednost + in + predmet + zgolj + dva + dve + plati + istega + odnosa + + + ker + eee + je + vse + kar + vemo + eee + eee + vse + kar + nam + je + dano + od + predmeta + vsebovano + v + vednosti + o + predmetu + in + ne + obstaja + neka + druga + vednost + eee + vednost + ki + ne + bi + bila + zavednost + + + ne + se + pravi + vprašanje + je + to + je + bilo + to + je + tisto + o + čemer + smo + zadnjič + eee + končali + + + vprašanje + se + glasi + kako + lahko + to + kar + je + zgolj + dvojna + plat + to + kar + sta + zgolj + dve + plati + enega + in + istega + odnosa + kako + je + lahko + to + kar + je + po + vsebini + nujno + identično + kako + lahko + to + pride + v + nesovpadanje + + + kako + se + lahko + tukaj + sploh + pojavi + eee + razlika + + + to + kar + smo + opozorili + je + zgolj + to + eee + da + Hegel + tukaj + uporablja + neko + razliko + med + za + zavest + in + ta + predmet + je + za + zavest + ampak + hkrati + ji + tudi + je + kot + predmet + in + ta + razlika + med + za + zavest + in + zavesti + se + pravi + za + plus + akuzativ + in + dvojni + dativ + eee + da + je + ta + + raz + + + de + + d + + + da + bo + nekako + na + ta + + n + + + na + na + tej + razliki + treba + opreti + možnost + na + to + razliko + opreti + možnost + da + pride + do + nesovpadanja + + + eee + neskladja + med + vednostjo + in + predmetom + pri + čemer + ta + ji + označuje + tisti + moment + po + katerem + eee + je + predmet + tuj + zavesti + ne + + + po + kateri + predmet + kot + objekt + ravno + nastopa + kot + nekaj + kar + je + neodvisno + od + eee + subjekta + + + eee + kot + nekaj + kar + obstaja + vsaj + po + pretenziji + neodvisno + od + tega + ali + zavest + zanj + ve + ali + ne + ne + + + to + je + eee + zdej + eee + trenutno + stanje + obenem + smo + rekli + eee + da + + + + + + + + + + trenutno + ni + jasno + seveda + lahko + preberemo + besedilo + in + eee + povzamemo + kaj + Hegel + pravi + ampak + da + ni + najbolj + jasno + kako + naj + to + razumemo + in + da + bomo + poskušali + na + podlagi + eem + rcimo + sledi + ki + jih + bo + Hegel + pustil + ki + jih + Hegel + pušča + prej + in + pozneje + ko + opisuje + to + ta + dogodek + sklepati + eee + da + bomo + skratka + poskušali + na + podlagi + teh + sledi + sklepati + za + kaj + pravzaprav + pri + tem + gre + + + kako + pride + do + eee + kako + lahko + pride + do + neskladja + med + vednostjo + in + predmetom + + + + + + + + + + eee + če + zej + preberemo + še + še + enkrat + zadnjič + se + prai + če + tem + primerje + + + se + prai + toda + ravno + v + tem + da + nasploh + ve + o + nekem + predmetu + je + že + navzoča + ta + razlika + da + je + njej + to + je + tista + ji + nekej + nasebje + neki + drugi + moment + pa + vednost + ali + bit + predmeta + za + zavest + + + na + tem + razločku + ki + je + navzoč + sloni + preizkus + + + to + smo + rekli + ne + + + če + si + v + tej + primerjavi + oboje + ne + ustreza + potem + se + zdi + da + mora + zavest + spremeniti + svojo + vednost + da + bi + jo + prilagodila + predmetu + + + toda + v + spremembi + vednosti + se + ji + dejansko + spremeni + tudi + predmet + sam + kajti + navzoča + vednost + je + bila + bistvena + vednost + o + predmetu + + + skupaj + z + vednostjo + tudi + predmet + postane + drug + kajti + ta + predmet + je + bistveno + pripadal + tej + vednosti + + + in + to + si + moramo + zmerej + + zap + + + eee + eee + zapomniti + + + ta + predmet + je + bistveno + pripadal + tej + vednosti + + + vednost + in + predmet + se + vzajemno + sodoločata + + + kakor + se + spremeni + vednost + se + pravi + kakor + se + spremeni + neka + podoba + naravne + zavesti + tako + se + spremeni + tudi + predmet + + + in + obratno + kakor + se + spremeni + predmet + tako + se + spremeni + tudi + vednost + se + pravi + + ka + + + s + spremembo + predmeta + tudi + ena + podoba + naravne + zavesti + prestane + neko + spremembo + in + morda + eem + postane + druga + podoba + naravne + zavesti + + + eee + kajti + vemo + tudi + v + tistem + kar + eee + vednost + razglaša + za + svoj + predmet + in + to + pomeni + za + tisto + eee + v + tistem + kar + eee + zavest + razglaša + za + svoj + resnični + predmet + bomo + imeli + kriterij + da + merimo + eee + vednost + po + njej + imanentni + po + njem + imanentni + kriterij + + + + + + + + + + torej + eee + + kajti + ta + predmet + je + bistveno + pripadov + tej + vednosti + + + s + tem + postane + zavesti + očitno + da + tisto + kar + ji + je + bilo + prej + nasebje + ni + bilo + na + sebi + ali + da + je + bilo + le + za + njo + na + sebi + + + tu + je + zej + eden + od + ključnih + stavkov + se + pravi + zavesti + postane + očitno + da + tisto + kar + ji + je + ji + je + bilo + nasebje + se + pravi + ji + je + bilo + nasebje + ji + je + bil + objekt + kolikor + to + označuje + neko + razliko + med + za + zavest + in + ji + ne + zavesti + ni + bilo + na + sebi + ali + da + je + bilo + le + za + njo + na + sebi + + + se + pravi + kaj + se + izkaže + v + tem + aaa + sesutju + se + pravi + ob + + primer + + + v + primeru + ko + si + ta + ti + dve + plati + na + ustrezata + ? + + + izkaže + se + to + da + tisto + kar + ji + je + bilo + nasebje + ni + nasebje + ampak + da + ji + je + bilo + za + njo + + nase + + + + na + + + nasebje + + + in + v + tem + vidimo + kako + lahko + govorimo + moment + uvedenja + eee + v + tem + lahko + vidimo + moment + uvedenja + subjetkivne + vpetosti + + + skratka + lahko + se + zdi + da + + j + + + smo + imeli + pred + tem + neko + neposredno + naivno + predstavo + naravne + zavesti + ki + je + nekam + postavljala + svoj + resnični + predmet + in + ki + ga + je + imela + za + resnični + predmet + ne + zgolj + + z + + + resnični + predmet + za + njo + ko + pa + pride + do + tega + neskladja + se + + p + + + ooo + eee + se + se + manifestira + tisto + kar + je + bilo + + pro + + + eee + provzaprov + očitno + da + je + bila + ta + predstava + resničnega + predmeta + to + pojmovanje + resničnega + predmeta + podpogojeno + z + neko + subjektivno + pozicijo + + + + + + + + + + da + je + lahko + ta + predmet + nastopal + kot + resnični + predmet + zgolj + s + tiste + pozicije + ki + je + sedaj + ni + več + a + ne + + + + + + + + + + aaa + se + pravi + mmm + kaj + to + kar + ji + je + + bi + + + + + + ka + + + + k + + + kaj + se + zdaj + zgodi + rekli + smo + razlika + je + eee + + + + + + + + + + Hegel + opozarja + na + razliko + med + za + zavest + in + zavesti + + + me + za + njo + in + njej + + + za + njo + in + ji + ne + + + in + ko + pride + do + neskladja + ne + pravi + eee + če + si + v + tej + primerjavi + oboje + ne + ustreza + se + zgodi + kaj + + + nasebje + ki + ji + je + bilo + postane + nasebje + za + njo + + + tisto + kar + ji + je + bilo + zdej + dobi + status + za + njo + + + preide + eee + + eks + + + eee + eksplicitno + v + moment + vednosti + + + tako + da + bi + lahko + tukaj + si + lahko + naredite + se + prai + da + tisto + kar + ji + j + bilo + prej + nasebje + ni + bilo + na + sebi + na + sebi + ali + da + je + bilo + na + sebi + le + za + njo + + + to + kar + ji + je + bilo + prej + + na + + + kar + ji + je + bilo + nasebje + je + zdaj + na + sebi + le + za + njo + + + iz + momenta + ji + preide + na + moment + za + njo + + + to + se + zgodi + to + zdej + recimo + na + podlagi + tega + kar + Hegel + pravi + vidimo + + + kaj + to + pomeni + tega + še + ne + vemo + + + ko + torej + zaves + o + predmetu + ugotovi + da + mu + njena + vednost + ne + ustreza + tudi + predmet + sam + ne + vzdrži + + + ali + merilo + preizkusa + se + spremeni + če + tisto + česar + merilo + naj + bi + bilo + v + preizkusu + ne + obstane + + + recimo + preizkus + ni + samo + preizkus + vednosti + temveč + tudi + njenega + merila + + + + + + + + + + in + zdej + gremo + naprej + a + ne + + + + + + + + + + eee + naprej + pa + zdej + stavek + ki + je + morda + eden + od + ključnih + mism + en + od + ključnih + eden + od + številnih + ključnih + stavkov + a + ne + + eee + ki + se + jih + je + dobro + zapomniti + + + pravi + Hegel + to + dialektično + gibanje + ki + ga + zavest + izvaja + sama + na + sebi + tako + na + svoji + vednosti + kakor + na + svojem + predmetu + čakajte + da + pogledam + + + + + + + + + + sama + na + sebi + namreč + lahko + bi + rekli + izvaja + sama + na + sebi + izvaja + sama + s + seboj + tudi + tako + bi + bilo + eee + mogoče + to + + + + dize + dialektiše + bevegung + velhe + das + bevus + zajn + an + im + zelbst + zavol + am + zajnem + bisen + als + am + zajnem + gegenštande + ausibt + + + + ne + se + pravi + to + dialektično + gibanje + ki + ga + zavest + izvaja + sama + na + sebi + tako + na + svoji + vednosti + kakor + na + svojem + predmetu + kolikor + ji + iz + tega + nastane + nov + resnični + predmet + je + provzaprov + tisto + kar + se + imenuje + izkustvo + + + in + če + tukaj + govorimo + o + v + v + + na + + + o + našem + kontekstu + je + kakšno + izkustvo + seveda + izkustvo + zavesti + ne + + + kar + je + pomembno + a + ne + + + zakaj + zaradi + tega + ker + je + ker + je + kot + vemo + začetni + naslov + Fenomenologije + duha + bil + Znanost + izkustva + zavesti + + + in + tuki + mamo + zdej + pač + deklaracijo + izjavo + definicijo + kaj + Hegel + misli + z + izkustvom + zavesti + + + dialektično + gibanje + zavest + ga + izvaja + sama + na + sebi + sama + s + seboj + pri + tem + ji + nastane + nov + resnični + predmet + je + provzaprov + tisto + kar + se + imenuje + izkustvo + + + + + + + + + + pravi + dialektično + gibanje + preizkus + realnosti + vednosti + vemo + celo + to + da + v + tem + eee + da + + go + + + lahko + govorimo + o + izkustvu + zavesti + kolikor + ji + nastane + nov + resnični + predmet + + + + toli + + + torej + kolikor + ji + stari + resnični + predmet + propade + + + torej + + iz + + + o + izkustvu + zavesti + lahko + govorimo + provzaprov + samo + tedaj + eem + ko + + + + + + + + + + se + izkaže + + k + + + ko + se + pokaže + neskladje + med + vednostjo + in + predmetom + ne + + + to + dialektičo + gibanje + pri + preizkusu + realnosti + vednosti + + + + + + + + + + kolikor + zavesti + pri + tem + nastane + nov + resnični + predmet + in + pomembno + je + da + nastane + nov + resnični + predmet + + + + + + + + + + zej + kako + nej + zdej + to + razumemo + + + + + + + + + + dej + lahko + gremo + lahko + gremo + naprej + da + dobimo + še + kakšno + sled + bi + pa + za + začetek + opozoril + samo + na + en + izraz + in + to + je + + dize + dialektiše + bevegung + + to + dialektično + gibanje + + + zej + Hegel + dialektik + + + Hegel + uporablja + izraz + tako + kot + danes + uporabljamo + izraz + dialektika + pogosto + v + vsakdanjem + pomenu + ne + kot + besedo + vsakdanje + govorice + eee + tako + kot + se + dialektika + danes + pogosto + uporablja + kot + psovka + + + ampak + včasih + uporablja + v + togem + Heglovem + pomenu + in + mislim + da + je + to + eden + od + teh + primerov + + + zato + bomo + pogledali + kaj + pravi + o + dialektiki + v + mmm + pravzaprav + nenaključnem + tekstu + na + koncu + Znanosti + logike + iz + leta + tisoč + osemsto + šesnajst + + + se + pravi + pod + poglavjem + + aboslute + ide + + absolutna + ideja + s + čimer + se + Znanost + logike + konča + tako + kot + se + Fenomenologija + duha + konča + z + absolutno + vednostjo + tako + se + Znanost + logike + konča + z + absolutno + idejo + + + idejo + ki + spet + deluje + kot + nekakšen + antiklimaks + zaradi + tega + ker + ne + pride + do + eee + razsvetlenja + razsvetlitve + ampak + Hegel + nekako + reče + sej + no + zdej + smo + na + koncu + zdej + je + stvar + jasna + + povejm + + + poglejmo + samo + še + nekaj + metodičnih + preudarkov + kako + smo + do + tod + prišli + + + v + resnici + samo + o + metodi + + + ampak + to + kar + je + za + nas + pomembno + je + da + tukej + pravzaprav + eee + poda + neko + dovolj + natančno + oziroma + dovolj + uporabno + opredelitev + dialektike + + + in + pravi + bistveno + je + da + eem + absolutna + metoda + najde + in + spozna + določitev + občega + v + njem + samem + + + razumsko + končno + spoznavanje + postopa + pri + tem + tako + da + tisto + kar + je + pri + abstirharujočem + proizvajanju + onega + občega + opustilo + sedaj + enako + zunanje + znova + povzame + od + konkretnega + + + se + pravi + razlika + med + razumsko + eee + metodo + ki + je + zunanja + in + absolutno + medoto + ki + je + Heglova + + + absolutna + metoda + pa + se + ne + vede + kot + zunanja + refleksija + temveč + določeno + jemlje + od + svojega + predmeta + samega + saj + je + ona + sama + njegov + imanentni + princip + in + duša + + + to + je + tisto + kar + je + od + spoznavanja + zahteval + Platon + namreč + da + je + treba + reči + obravnavati + same + za + sebe + + + reči + je + treba + obravnavati + same + za + sebe + deloma + v + njihovi + občosti + deloma + pa + ne + odbloditi + od + njih + in + posegati + po + okoliščinah + eksemplih + in + primerjavah + temveč + imeti + pred + seboj + edino + nje + in + spraviti + do + zavesti + to + kar + je + imanentno + njih + obravnavati + reči + same + po + sebi + + + obravnavati + jih + imanentno + ne + da + bi + eee + posegali + z + lastnimi + domislicami + v + njihovo + obravnavo + + + to + smo + videli + natanko + enako + eee + je + tukaj + govoru + Hegel + za + eee + to + kako + naj + poteka + preizkus + realnosti + vednosti + + + metoda + absolutnega + spoznavanja + je + toliko + analitična + da + nadaljno + določitev + svojega + začetnega + občega + najde + povsem + le + v + njem + ki + je + absolutna + objektivnost + pojma + katerega + + g + + + gotovost + je + + + se + pravi + ta + absolutna + metoda + je + analitična + ker + izhaja + iz + obravnave + svojega + predmeta + samega + ni + nič + drugega + kot + + + + + + + + + + opazovanje + ni + opazovanje + je + kot + analiza + tega + kar + se + ponuja + ne + + + vendar + je + v + enaki + meri + tudi + sintetična + saj + se + njen + predmet + ki + je + neposredno + določen + kot + enostavno + obče + spričo + določnosti + ki + jo + ima + v + svoji + neposrednosti + in + občosti + sami + pokaže + kot + nekaj + drugega + + + ta + odnos + različnega + ki + tako + njen + + predme + + + ki + tako + njen + predmet + je + v + sebi + pa + nikakor + ni + več + tisto + kar + je + mišljeno + kot + sinteza + pri + končnem + spoznavanju + + + že + zaradi + svoje + prav + tako + tudi + analitične + določitve + nasloh + da + je + odnos + v + pojmu + se + popolnoma + razlikuje + od + te + sintetičnosti + + + skratka + kaj + smo + videli + metoda + je + analitična + kolikor + obravnava + svoj + predmet + imanentno + kolikor + ne + dodaja + zunanjih + določil + + + vednar + je + hkrati + tudi + sintetična + + + ne + sintetična + v + smislu + da + bi + dodala + nekaj + drugega + od + zunaj + kot + to + počne + razumska + sinteza + ampak + sinteza + v + smislu + da + skozi + analizo + nekega + predmeta + nekega + pojma + proizvede + druga + določila + + + spravi + na + plan + tisto + s + čimer + je + bilo + to + določilo + povezano + in + kar + je + potemtakem + bilo + moralo + biti + vsebovano + v + njem + + + to + da + postane + začetni + pojem + drug + je + ta + sintetični + moment + + + se + pravi + eee + pokaže + kot + nekej + drugega + in + pravi + + + ta + tako + sintetični + kakor + tudi + analitični + moment + sodbe + + + + + + + + + + ne + tako + analitični + + ta + + + + ta + + + tako + sintetični + kakor + tudi + analitični + moment + sodbe + na + podlagi + katerega + se + začetno + obče + samo + iz + sebe + določi + kot + drugo + sebe + kot + svoje + drugo + bi + imenovali + + das + dialektiše + + + + to + bi + imenovali + tisto + dialektično + + + torej + ta + + t + + + ta + moment + ki + je + tako + analitičen + kot + sintetičen + videli + smo + zakaj + analitičen + zaradi + tega + ker + je + imanenten + sintetičen + zaradi + tega + ker + proizvode + + ne + + + proizvede + neko + nadaljne + določilo + ki + + nepo + + + v + neposrednem + predmetu + kakor + smo + začeli + ni + bilo + vsebovano + + + se + pravi + ta + tako + sintetični + kakor + tudi + analitični + moment + sodbe + na + podlagi + katerega + se + začetno + obče + samo + iz + sebe + določi + kot + svoje + drugo + kot + drugo + sebe + kot + nekaj + drugega + bi + imenovali + tisto + dialektično + + + + + + + + + + dialektično + je + torej + dialektična + obravnava + je + potemtakem + obravnava + + + če + vzamemo + samo + to + kar + smo + zdej + povedali + + + Hegel + potem + nadaljuje + češ + + k + + + kako + je + bila + dialektika + pojmovana + pri + Platonu + pri + pri + Grkih + nasploh + kako + je + eee + posebna + zasluga + eee + Kanta + da + je + pokazal + kako + so + reči + + je + pokazal + kako + je + protislovje + eee + ravno + v + dialektitki + čistega + uma + kako + je + protislovje + nujna + značilnost + predmeta + + + ne + naključna + napaka + ampak + nekaj + v + kar + nas + sili + eee + imanentna + obravnava + sveta + samega + + + skratka + to + + t + + + + t + + + ta + njegova + umestitev + eee + do + recimo + različnih + pojmovajn + dialektike + eee + sledi + ampak + kar + je + pomembno + za + nas + je + da + je + dialektika + imanentna + obravnava + nekega + predmeta + ki + pokaže + kako + so + v + tem + predmetu + vsebovana + druga + določila + + + + + + + + + + ki + pokaže + kako + nek + začetni + predmet + sam + iz + sebe + proizvede + svoje + drugo + + + kako + začetno + obče + samo + iz + sebe + na + podlagi + določil + ki + jih + ima + v + sebi + preide + v + nekaj + drugega + in + s + tem + vzpostavi + prostislovje + imanentno + antinomijo + bi + lahko + rekli + s + tistim + kar + je + na + začetku + bil + + + zakaj + je + to + pomembno + ? + + + + + + + + + + eeh + zaradi + tega + ker + smo + pač + ravno + si + zastavili + vprašanje + kako + lahko + pride + do + neskladja + med + + predme + + + eee + med + vednostjo + in + predmetom + + + kako + lahko + skozi + preizkus + realnosti + eee + vednosti + ugotovimo + da + se + ti + dve + plati + ne + ujemata + + + zde + lahko + rečemo + + n + + + na + podlagi + te + analogije + a + ne + na + na + podlagi + te + primerjave + eee + da + bo + lahko + šlo + za + to + da + izhajamo + iz + neke + pozicije + vednosti + ju + obravnavamo + samo + po + sebi + in + ugotovimo + tako + kot + v + dialektični + obravnavi + nasploh + kakšne + so + kakšne + + + se + pravi + ugotovimo + kaj + izhaja + iz + teh + določil + in + pridemo + do + spoznanja + da + nam + je + začetno + določilo + se + sprevrglo + v + svoje + drugo + + + da + je + postalo + nekej + drugega + kot + je + bilo + prej + + + namreč + dialektika + pri + pri + eee + Heglu + če + + u + + + če + uporabimo + te + znane + široko + uporabljene + in + eee + + zlob + + + zlorabljene + izraze + teza + in + antiteza + ne + pomeni + da + imamo + najprej + tezo + potem + pa + eee + na + drugo + stran + postavimo + antitezo + in + da + bomo + zdej + to + da + bomo + preko + tega + vzpostavili + dialektično + sintezo + ampak + nasprotno + + + eee + dialektična + Heglova + imanentna + obravnava + je + v + tem + da + pokaže + kako + teza + sama + v + + s + + + sama + po + sebi + na + podlagi + lastnih + konsekvenc + preide + v + svoje + nasprotje + + + kako + teza + in + antiteza + nista + zunanji + nasprotji + ampak + kako + teza + sama + preide + v + antitezo + kako + je + antiteza + antiteza + teze + same + + + kako + je + antiteza + vsebovana + v + tezi + + + in + podobno + bomo + videli + poskušali + domnevam + lahko + zdaj + domnevamo + bo + Hegel + pri + preizkusu + realnosti + vednosti + poskušal + pokazati + kako + je + vednost + v + resnici + ki + jo + pač + opredelimo + z + rcimo + nekim + resničnim + predmetom + potem + preizkusimo + kaj + je + na + sebi + in + ugotovimo + da + je + ta + vednost + v + resnici + drugo + sama + sebe + + + da + vednost + ve + nekej + drugega + kot + se + je + zdelo + na + začetku + + + izidemo + iz + neke + začetne + neposredne + opredelitve + pogledamo + kaj + to + pomeni + potegnemo + konsekvence + jo + obravnavamo + samo + po + sebi + torej + analitično + hkrati + tudi + sintetično + ker + proizvedemo + določila + ki + so + bila + predtem + samo + mmm + ki + so + povezana + s + tem + in + ugotovimo + da + nazadnje + + pri + + + dobimo + v + roke + nekej + drugega + kot + je + bilo + tisto + s + čimer + smo + mislili + da + smo + začeli + + + + + + + + + + ja + + + + + + + + + + to + se + bo + nadaljevalo + vse + dokler + dokler + ne + bomo + nekako + preprečili + eee + + + + + + + + + + migotanja + širjenja + aaa + te + drugosti + res + je + + + eee + eno + je + vprašanje + kako + recimo + se + + de + + + provzaprov + se + zdej + eee + eee + smo + si + zastavili + vprašanje + kako + se + sploh + vzpostavi + neskladje + med + vednostjo + in + predmetom + torej + kako + pride + do + te + + drugosti + + + kako + pridemo + do + prvega + i + drugega + kako + se + torej + ta + to + gibanje + ta + dialektični + proces + začne + + + to + je + eno + vprašanje + + + poskušali + smo + nakazati + smer + v + katero + je + + tre + + + v + kateri + je + treba + iskati + odgovor + + + drugo + vprašanje + pa + je + to + ko + se + enkat + stvar + zažene + ko + enkrat + vidimo + da + z + imanentno + obravnavo + pridemo + do + drugega + da + isto + samo + po + sebi + postane + drugo + je + vprašanje + kje + se + lahko + fenomenologije + duha + ali + kje + se + Heglova + obravnava + česarkoli + kakršnegakoli + določila + sploh + lahko + zaključi + + + empirično + vemo + da + se + zaključi + + + zaključi + se + v + neki + točki + ki + ji + reče + absolutna + vednost + + + se + pa + strinjam + da + to + je + eno + od + eee + recimo + občutljivih + točk + eee + Heglove + + s + + + Heglovega + sistema + + + jasno + lahko + rečemo + tudi + nekoliko + drugače + Hegel + je + je + mislec + protislovja + Hegel + je + mislec + eee + po + za + katerega + protislovje + ne + sicer + kakršnokoli + protislovje + torej + na + arbitrarnost + imanentno + protislovje + deluje + kot + znamenje + resničnega + + + ampak + jasno + ko + enkrat + spustimo + protislovje + na + plano + ne + potem + se + zdi + da + bomo + imeli + velike + težave + kako + ta + duh + spraviti + nazaj + v + steklenico + in + to + je + vprašanje + kako + Heglov + sistem + zaklučiti + + + kako + reči + zdej + smo + prišli + pa + do + drugega + ki + nima + več + svojega + drugega + ne + + + ampak + ja + + z + + + + z + + + zgoditi + se + mora + nekej + takega + in + Hegel + vsekakor + vztraja + na + tem + da + se + v + neki + točki + + ta + + pr + + + proces + zaupogne + vase + tako + rekoč + zaokroži + in + s + tem + sklene + + vase + skratka + dobi + podobo + eee + dokončnosti + cimo + + + dokončnosti + za + razliko + od + recimo + eee + kakšnega + Deridaja + + + Derida + je + Derida + je + recimo + nekdo + ki + je + provzaprov + zelo + podoben + eee + po + metodi + obravnave + Heglu + + + ki + povsod + pokaže + kako + je + enotnost + vedno + že + + navče + + + načeta + z + neko + razliko + + + z + tistim + diferons + ne + + + aaa + in + Derida + vztraja + pri + tem + da + je + diferons + v + resnici + tisto + zadnje + tako + da + pri + njem + nikoli + ne + pride + do + eee + sklenitve + zaokroženja + eee + ker + bi + to + pomenilo + kao + padec + nazaj + v + metafizični + eee + diskurz + + + in + si + ne + + b + + + si + v + svojih + najbolj + slavnih + trenutkih + ne + bo + dovolil + doreči + niti + tega + da + se + nikoli + ne + bo + eee + zaklučilo + zaradi + tega + ker + bi + to + že + pomenilo + da + postavlja + neke + dokončne + eem + trditve + + + in + to + je + cimo + tisto + kar + bi + Hegel + imenoval + dolgočasnost + dekonstrukcije + + + eee + eee + kmalu + + začn + + + eee + začne + postajati + dolgočasno + ne + eee + kot + je + nekje + že + prej + mislim + da + v + zvezi + s + skepticizmom + eee + povedal + + + ja + skratka + gre + za + to + da + moramo + najprej + + skatka + moramo + + eem + + + + + + + + + + zaustaviti + to + širjenje + dobro + recimo + zelo + hitro + to + pomeni + da + je + treba + eee + to + drugo + zaupogniti + ga + ubrniti + vase + tako + da + nekdo + se + pravi + neka + subjektna + pozicija + postane + sama + svoje + drugo + tako + da + v + drugem + preide + k + sebi + + + torej + če + je + če + je + nekaj + drugo + samega + sebe + potem + nima + več + drugega + oziroma + ima + drugo + ampak + v + drugem + pride + eee + do + sebe + in + lahko + rečemo + še + drugače + + + eee + eee + zadeva + se + zaustavi + v + točki + kjer + se + razlika + ki + je + bila + pred + tem + zunanja + eno + in + drugo + ponotranji + + + spet + splošna + formula + jasno + pa + je + da + Fenomenologija + duha + ne + bi + obsegala + šeststo + strani + če + bi + bilo + to + po + Heglu + mogoče + naredit + eee + na + vsaki + točki + + + tudi + potem + v + sami + + fe + + + eee + fenomenologiji + ko + cimo + na + koncu + poglavja + o + razumu + eee + se + vzpostavi + zrenje + notranjega + v + notranje + + + eee + in + ko + + sam + + + eee + ko + zastor + pred + nasebnostjo + pade + in + samozavedanje + stopi + za + zaveso + pravi + Hegel + eee + tako + zato + eee + da + bi + bilo + da + bi + lahko + videla + kaj + je + tam + za + zaveso + kot + tudi + zato + da + bi + bilo + za + zaveso + sploh + kaj + kar + bi + bilo + moč + vedeti + ne + + + eee + več + skratka + to + se + zgodi + tedaj + in + + rej + + + eee + reče + na + ta + način + se + izkaže + da + je + bil + bila + predmet + zgolj + zavest + sama + ne + izkaže + pa + se + tudi + da + zadaj + za + zaveso + ni + bilo + ničesar + razen + zavesti + same + + + je + izkaže + se + pa + tudi + da + ni + mogoče + kar + tako + stopiti + eee + na + ono + stran + za + zastor + + + tudi + ko + govorimo + + en + + + enako + tudi + tukaj + bi + rekli + + + eee + lahko + rečemo + kakšen + kakšne + zahteve + mora + izpolnjevati + zadnji + korak + da + bi + cimo + zacelil + celotno + eee + zgradbo + vendar + pa + ni + mogoče + tega + koraka + naredit + na + vsaki + točki + eee + sistema + + + enako + kot + tudi + če + rečemo + da + Hegel + dopušča + protislovje + to + ne + pomeni + zdej + da + bomo + govorili + čim + več + protislovij + bomo + trosili + bližje + bomo + resnici + + + protislovje + pri + Heglu + mora + bit + imanentno + protislovje + se + pravi + protislovje + do + katerega + pridemo + po + nujnosti + stvari + same + ne + pa + zunanjepostavljeno + eden + pravi + tako + drugi + pravi + drugače + to + dvoje + je + protislovno + ampak + sej + protislovje + je + znamenje + resnice + + + gre + za + to + da + mora + iz + neke + začetne + opredelitve + kolikor + pridemo + do + + protislovi + + + mmm + skratka + da + mora + bit + to + protislovje + izpeljano + imanentno + in + tedaj + pa + pravi + ja + je + protislovje + ampak + tega + se + ne + ustrašit + ne + + + eee + to + je + ravno + znamenje + da + smo + na + pravi + poti + treba + je + vztrajati + do + konca + + + treba + je + zdej + misliti + to + protislovje + + + to + je + potem + prava + naloga + ne + samo + pokazati + ampak + ga + misliti + ga + ubvladati + + + dobro + če + gremo + zdaj + nazaj + to + dialektično + gibanje + + + + + + + + + + gre + za + imanentno + samodrugotenje + ne + + + + + + + + + + če + govorimo + o + vednosti + preizkusu + + ve + + + se + prai + če + govorimo + o + momentu + dialektičnosti + bo + očitno + šlo + za + to + da + preizkus + realnosti + vednosti + tista + vednost + ki + se + je + najprej + imela + za + vednost + + z + + + da + se + bo + tista + vednost + izkazala + za + nekaj + drugega + kot + se + je + zdelo + na + začetku + + + kot + je + bilo + opredeljeno + na + začetku + + + na + ta + način + bo + tisto + kar + ji + je + bilo + resnično + hkrati + postalo + resnično + al + nasebje + samo + za + njo + + + seveda + če + bomo + videli + da + je + prišlo + do + neskladja + to + + l + + + eee + lahko + samo + pomeni + da + se + nahajamo + v + v + zmoti + + + to + se + lahko + eee + to + lahko + + s + + + pomeni + da + se + nahajamo + eee + na + nekem + parcialno + pogojenem + stališču + s + čimer + bo + naravna + zavest + se + na + nek + način + ovedla + svoje + lastne + vpetosti + v + eee + pač + proces + spoznavanja + + + in + drugo + kar + je + treba + vedeti + + + + n + + + eno + eno + je + ta + dialektični + moment + + + eee + drugo + je + pa + to + da + Hegel + ta + + d + + + to + dialektiko + se + pravi + imanentno + proizvajanje + drugega + + + + + + + + + + imanentno + izpeljavo + + + + + + + + + + sebi + drugega + obravnava + po + modelu + izkustva + + + po + modelu + izkustva + zavesti + + + eee + zmerej + gre + za + to + da + se + zavest + sama + sooča + + poskuša + realizirat + ob + svojem + predmetu + + + in + ob + predmetu + torej + ob + poskusu + spoznanja + očitno + ugotovi + da + njen + predmet + kakor + ga + je + postavila + na + začetku + kakor + ji + je + bil + in + predmet + kakor + ga + potem + dejansko + spozna + kakor + potem + dejansko + je + za + njo + da + si + to + dvoje + ne + ustreza + + + + + + +