<commit_before>package nl.mpi.kinnate.entityindexer;

import nl.mpi.kinnate.uniqueidentifiers.UniqueIdentifier;
import nl.mpi.kinnate.kintypestrings.KinTypeStringConverter;
import nl.mpi.kinnate.kintypestrings.KinTypeStringConverter.QueryTerm;

/**
 *  Document   : QueryBuilder
 *  Created on : Mar 23, 2011, 3:32:23 PM
 *  Author     : <NAME>
 */
public class QueryBuilder {

    public String asSequenceString(String[] stringArray) {
        StringBuilder stringBuilder = new StringBuilder();
        for (String currentEntry : stringArray) {
            if (stringBuilder.length() > 0) {
                stringBuilder.append(",");
            } else {
                stringBuilder.append("(");
            }
            stringBuilder.append("\"");
            stringBuilder.append(currentEntry);
            stringBuilder.append("\"");
        }
        stringBuilder.append(")");
        return stringBuilder.toString();
    }

    public String asSequenceString(IndexerParam indexerParam) {
        StringBuilder stringBuilder = new StringBuilder();
        for (ParameterElement currentEntry : indexerParam.getValues()) {
            if (stringBuilder.length() > 0) {
                stringBuilder.append(",");
            } else {
                stringBuilder.append("(");
            }
            stringBuilder.append("\"");
            stringBuilder.append(currentEntry.getXpathString());
            stringBuilder.append("\"");
        }
        stringBuilder.append(")");
        return stringBuilder.toString();
    }
//.    excape quotes from symbol queries
//. when getting the icon clause and the symbol the string input must be encoded for ' " &
//.        http://www.balisage.net/Proceedings/vol7/html/Vlist02/BalisageVol7-Vlist02.html#d38243e274

    public String getLabelsClause(IndexerParameters indexParameters, String docRootVar) {
        StringBuilder stringBuilder = new StringBuilder();
        for (ParameterElement currentEntry : indexParameters.labelFields.getValues()) {
//            String trimmedXpath = currentEntry.getXpathString(); //.substring("*:Kinnate/*:Entity".length()); // todo: remove this and update the indexParameters entries
            stringBuilder.append("for $labelNode in ");
            stringBuilder.append(docRootVar);
            stringBuilder.append(currentEntry.getXpathString());
            stringBuilder.append("\nreturn\ninsert node <kin:Label xmlns:kin=\"http://mpi.nl/tla/kin\">{$labelNode/text()}</kin:Label> after $copyNode/*:Identifier,\n"); // into $copyNode
        }
        return stringBuilder.toString();
    }

    public String getSymbolClause(IndexerParameters indexParameters, String docRootVar) {
        StringBuilder stringBuilder = new StringBuilder();
        for (ParameterElement currentEntry : indexParameters.symbolFieldsFields.getValues()) {
            String trimmedXpath = currentEntry.getXpathString().substring("*:Kinnate".length());
            stringBuilder.append("if (exists(");
            stringBuilder.append(docRootVar);
            stringBuilder.append(trimmedXpath);
            stringBuilder.append(")) then ");
            stringBuilder.append("insert node <kin:Symbol xmlns:kin=\"http://mpi.nl/tla/kin\">");
            stringBuilder.append(currentEntry.getSelectedValue());
            stringBuilder.append("</kin:Symbol> after $copyNode/*:Identifier "); // into $copyNode
            stringBuilder.append("else (),\n");
        }
        return stringBuilder.toString();
    }

    public String getArchiveLinksClause() {
        return "for $corpusLink in $entityNode/*:CorpusLink\n"
                + "return <ArchiveLink>{$corpusLink/text()}</ArchiveLink>";
    }

    public String getRelationQuery() {
        return "<Relations>{"
                + "$entityNode/*:Relations\n"
                + "}</Relations>";
    }

//    public String getRelationQuery(String uniqueIdentifier, IndexerParameters indexParameters) {
//        String ancestorSequence = this.asSequenceString(indexParameters.ancestorFields);
//        String decendantSequence = this.asSequenceString(indexParameters.decendantFields);
//        return "<Relations>{" // todo: make the results here distinct and preferably only calculate each type once (this is currently handled in the entity data class)
//                + "for $relationNode in collection('nl-mpi-kinnate')/*:Kinnate/*:Relation[*:UniqueIdentifier/. = \"" + uniqueIdentifier + "\"]\n"
//                + "let $isAncestor := $relationNode/*:Type/text() = " + decendantSequence + "\n" // note that the ancestor and decentant are switched for alter compared to ego
//                + "let $isDecendant := $relationNode/*:Type/text() = " + ancestorSequence + "\n"
//                + "where $isAncestor or $isDecendant \n"
//                + "return \n"
//                + "<Relation>{\n"
//                + "if ($isAncestor)\n"
//                + "then <Type>ancestor</Type>\n"
//                + "else if ($isDecendant)\n"
//                + "then <Type>descendant</Type>\n"
//                + "else <Type>none</Type>,\n"
//                + "<Identifier>{$relationNode/../(*:Gedcom|*:Entity)/*:UniqueIdentifier/(*:LocalIdentifier|*:UniqueIdentifier)/text()}</Identifier>,\n"
//                // with the type value we are looking for one of GraphDataNode.RelationType: sibling, ancestor, descendant, union, none
//                + "<Path>{base-uri($relationNode)}</Path>,\n"
//                //                + "<Label>a label</Label>,\n"
//                + "<Line>" + DataTypes.RelationLineType.sanguineLine.name() + "</Line>\n"
//                + "}</Relation>\n"
//                + "} {\n"
//                // for $relationNode in collection('nl-mpi-kinnate')/Kinnate/(Gedcom|Relation|Entity)[UniqueIdentifier/. = "742243abdb2468b8df65f16ee562ac10"]
//                // + "for $relationNode in collection('nl-mpi-kinnate')/*:Kinnate/(*:Gedcom|*:Entity)[*:UniqueIdentifier/. = \"" + uniqueIdentifier + "\"]\n"
//                + "for $relationNode in $entityNode/*:Relation\n"
//                + "let $isAncestor := $relationNode/*:Type/text() = " + ancestorSequence + "\n" // note that the ancestor and decentant are switched for alter compared to ego
//                + "let $isDecendant := $relationNode/*:Type/text() = " + decendantSequence + "\n"
//                + "where $isAncestor or $isDecendant \n"
//                + "return \n"
//                + "<Relation>{\n"
//                + "if ($isAncestor)\n"
//                + "then <Type>ancestor</Type>\n"
//                + "else if ($isDecendant)\n"
//                + "then <Type>descendant</Type>\n"
//                + "else <Type>none</Type>,\n"
//                + "<Identifier>{$relationNode/*:UniqueIdentifier/(*:LocalIdentifier|*:UniqueIdentifier)/text()}</Identifier>,\n" // todo: check this path to the identifier
//                // todo: add the alter unique identifier + "<UniqueIdentifier>" + uniqueIdentifier + "</UniqueIdentifier>,\n"
//                // with the type value we are looking for one of GraphDataNode.RelationType: sibling, ancestor, descendant, union, none
//                + "<Path>{base-uri(collection('nl-mpi-kinnate')/*:Kinnate[(*:Entity|*:Gedcom)/*:UniqueIdentifier/./text() = $relationNode/*:UniqueIdentifier/(*:LocalIdentifier|*:UniqueIdentifier)/text()])}</Path>,\n"
//                //                + "<Label>a label</Label>,\n"
//                + "<Line>" + DataTypes.RelationLineType.sanguineLine.name() + "</Line>\n"
//                + "}</Relation>"
//                + "}</Relations>\n";
//    }
    public String getEntityQueryReturn(IndexerParameters indexParameters) {
        return "return copy $copyNode := $entityNode\n"
                + "modify (\n"
                // loop the label fields and add a node for any that exist
                + this.getLabelsClause(indexParameters, "root($entityNode)/")
                + this.getSymbolClause(indexParameters, "root($entityNode)/")
                + "insert nodes <kin:Path xmlns:kin=\"http://mpi.nl/tla/kin\">{base-uri($entityNode)}</kin:Path> after $copyNode/*:Identifier\n" // when using a basex version younger than 6.62 the "after" fails re attributes: after $copyNode/*:Identifier" maybe copy is failing to keep the namespace, for earlier version the following can be used "into $copyNode"
                // todo: test if "insert after" take longer than "insert into"
                + ")\n"<commit_msg>Updated the date handling to allow for yyyy, yyyy/mm, yyyy/mm/dd and abt, bef and aft. Also provided more visual feedback when there is a date formatting error. Also modified the queries so that the date in the user data section is used on the diagram for the fist time.<commit_after>package nl.mpi.kinnate.entityindexer;

import nl.mpi.kinnate.uniqueidentifiers.UniqueIdentifier;
import nl.mpi.kinnate.kintypestrings.KinTypeStringConverter;
import nl.mpi.kinnate.kintypestrings.KinTypeStringConverter.QueryTerm;

/**
 *  Document   : QueryBuilder
 *  Created on : Mar 23, 2011, 3:32:23 PM
 *  Author     : <NAME>
 */
public class QueryBuilder {

    public String asSequenceString(String[] stringArray) {
        StringBuilder stringBuilder = new StringBuilder();
        for (String currentEntry : stringArray) {
            if (stringBuilder.length() > 0) {
                stringBuilder.append(",");
            } else {
                stringBuilder.append("(");
            }
            stringBuilder.append("\"");
            stringBuilder.append(currentEntry);
            stringBuilder.append("\"");
        }
        stringBuilder.append(")");
        return stringBuilder.toString();
    }

    public String asSequenceString(IndexerParam indexerParam) {
        StringBuilder stringBuilder = new StringBuilder();
        for (ParameterElement currentEntry : indexerParam.getValues()) {
            if (stringBuilder.length() > 0) {
                stringBuilder.append(",");
            } else {
                stringBuilder.append("(");
            }
            stringBuilder.append("\"");
            stringBuilder.append(currentEntry.getXpathString());
            stringBuilder.append("\"");
        }
        stringBuilder.append(")");
        return stringBuilder.toString();
    }
//.    excape quotes from symbol queries
//. when getting the icon clause and the symbol the string input must be encoded for ' " &
//.        http://www.balisage.net/Proceedings/vol7/html/Vlist02/BalisageVol7-Vlist02.html#d38243e274

    public String getLabelsClause(IndexerParameters indexParameters, String docRootVar) {
        StringBuilder stringBuilder = new StringBuilder();
        for (ParameterElement currentEntry : indexParameters.labelFields.getValues()) {
//            String trimmedXpath = currentEntry.getXpathString(); //.substring("*:Kinnate/*:Entity".length()); // todo: remove this and update the indexParameters entries
            stringBuilder.append("for $labelNode in ");
            stringBuilder.append(docRootVar);
            stringBuilder.append(currentEntry.getXpathString());
            stringBuilder.append("\nreturn\ninsert node <kin:Label xmlns:kin=\"http://mpi.nl/tla/kin\">{$labelNode/text()}</kin:Label> after $copyNode/*:Identifier,\n"); // into $copyNode
        }
        return stringBuilder.toString();
    }

    public String getDatesClause(IndexerParameters indexParameters, String docRootVar) {
        StringBuilder stringBuilder = new StringBuilder();
        for (ParameterElement currentEntry : indexParameters.dateOfBirthField.getValues()) {
//            String trimmedXpath = currentEntry.getXpathString(); //.substring("*:Kinnate/*:Entity".length()); // todo: remove this and update the indexParameters entries
            stringBuilder.append("for $dateOfBirthNode in ");
            stringBuilder.append(docRootVar);
            stringBuilder.append(currentEntry.getXpathString());
            stringBuilder.append("\nreturn\ninsert node <kin:DateOfBirth xmlns:kin=\"http://mpi.nl/tla/kin\">{$dateOfBirthNode/text()}</kin:DateOfBirth> after $copyNode/*:Identifier,\n"); // into $copyNode
        }
        for (ParameterElement currentEntry : indexParameters.dateOfDeathField.getValues()) {
//            String trimmedXpath = currentEntry.getXpathString(); //.substring("*:Kinnate/*:Entity".length()); // todo: remove this and update the indexParameters entries
            stringBuilder.append("for $dateOfDeathNode in ");
            stringBuilder.append(docRootVar);
            stringBuilder.append(currentEntry.getXpathString());
            stringBuilder.append("\nreturn\ninsert node <kin:DateOfDeath xmlns:kin=\"http://mpi.nl/tla/kin\">{$dateOfDeathNode/text()}</kin:DateOfDeath> after $copyNode/*:Identifier,\n"); // into $copyNode
        }
        return stringBuilder.toString();
    }

    public String getSymbolClause(IndexerParameters indexParameters, String docRootVar) {
        StringBuilder stringBuilder = new StringBuilder();
        for (ParameterElement currentEntry : indexParameters.symbolFieldsFields.getValues()) {
            String trimmedXpath = currentEntry.getXpathString().substring("*:Kinnate".length());
            stringBuilder.append("if (exists(");
            stringBuilder.append(docRootVar);
            stringBuilder.append(trimmedXpath);
            stringBuilder.append(")) then ");
            stringBuilder.append("insert node <kin:Symbol xmlns:kin=\"http://mpi.nl/tla/kin\">");
            stringBuilder.append(currentEntry.getSelectedValue());
            stringBuilder.append("</kin:Symbol> after $copyNode/*:Identifier "); // into $copyNode
            stringBuilder.append("else (),\n");
        }
        return stringBuilder.toString();
    }

    public String getArchiveLinksClause() {
        return "for $corpusLink in $entityNode/*:CorpusLink\n"
                + "return <ArchiveLink>{$corpusLink/text()}</ArchiveLink>";
    }

    public String getRelationQuery() {
        return "<Relations>{"
                + "$entityNode/*:Relations\n"
                + "}</Relations>";
    }

//    public String getRelationQuery(String uniqueIdentifier, IndexerParameters indexParameters) {
//        String ancestorSequence = this.asSequenceString(indexParameters.ancestorFields);
//        String decendantSequence = this.asSequenceString(indexParameters.decendantFields);
//        return "<Relations>{" // todo: make the results here distinct and preferably only calculate each type once (this is currently handled in the entity data class)
//                + "for $relationNode in collection('nl-mpi-kinnate')/*:Kinnate/*:Relation[*:UniqueIdentifier/. = \"" + uniqueIdentifier + "\"]\n"
//                + "let $isAncestor := $relationNode/*:Type/text() = " + decendantSequence + "\n" // note that the ancestor and decentant are switched for alter compared to ego
//                + "let $isDecendant := $relationNode/*:Type/text() = " + ancestorSequence + "\n"
//                + "where $isAncestor or $isDecendant \n"
//                + "return \n"
//                + "<Relation>{\n"
//                + "if ($isAncestor)\n"
//                + "then <Type>ancestor</Type>\n"
//                + "else if ($isDecendant)\n"
//                + "then <Type>descendant</Type>\n"
//                + "else <Type>none</Type>,\n"
//                + "<Identifier>{$relationNode/../(*:Gedcom|*:Entity)/*:UniqueIdentifier/(*:LocalIdentifier|*:UniqueIdentifier)/text()}</Identifier>,\n"
//                // with the type value we are looking for one of GraphDataNode.RelationType: sibling, ancestor, descendant, union, none
//                + "<Path>{base-uri($relationNode)}</Path>,\n"
//                //                + "<Label>a label</Label>,\n"
//                + "<Line>" + DataTypes.RelationLineType.sanguineLine.name() + "</Line>\n"
//                + "}</Relation>\n"
//                + "} {\n"
//                // for $relationNode in collection('nl-mpi-kinnate')/Kinnate/(Gedcom|Relation|Entity)[UniqueIdentifier/. = "742243abdb2468b8df65f16ee562ac10"]
//                // + "for $relationNode in collection('nl-mpi-kinnate')/*:Kinnate/(*:Gedcom|*:Entity)[*:UniqueIdentifier/. = \"" + uniqueIdentifier + "\"]\n"
//                + "for $relationNode in $entityNode/*:Relation\n"
//                + "let $isAncestor := $relationNode/*:Type/text() = " + ancestorSequence + "\n" // note that the ancestor and decentant are switched for alter compared to ego
//                + "let $isDecendant := $relationNode/*:Type/text() = " + decendantSequence + "\n"
//                + "where $isAncestor or $isDecendant \n"
//                + "return \n"
//                + "<Relation>{\n"
//                + "if ($isAncestor)\n"
//                + "then <Type>ancestor</Type>\n"
//                + "else if ($isDecendant)\n"
//                + "then <Type>descendant</Type>\n"
//                + "else <Type>none</Type>,\n"
//                + "<Identifier>{$relationNode/*:UniqueIdentifier/(*:LocalIdentifier|*:UniqueIdentifier)/text()}</Identifier>,\n" // todo: check this path to the identifier
//                // todo: add the alter unique identifier + "<UniqueIdentifier>" + uniqueIdentifier + "</UniqueIdentifier>,\n"
//                // with the type value we are looking for one of GraphDataNode.RelationType: sibling, ancestor, descendant, union, none
//                + "<Path>{base-uri(collection('nl-mpi-kinnate')/*:Kinnate[(*:Entity|*:Gedcom)/*:UniqueIdentifier/./text() = $relationNode/*:UniqueIdentifier/(*:LocalIdentifier|*:UniqueIdentifier)/text()])}</Path>,\n"
//                //                + "<Label>a label</Label>,\n"
//                + "<Line>" + DataTypes.RelationLineType.sanguineLine.name() + "</Line>\n"
//                + "}</Relation>"
//                + "}</Relations>\n";
//    }
    public String getEntityQueryReturn(IndexerParameters indexParameters) {
        return "return copy $copyNode := $entityNode\n"
                + "modify (\n"
                // loop the label fields and add a node for any that exist
                + this.getLabelsClause(indexParameters, "root($entityNode)/")
                + this.getDatesClause(indexParameters, "root($entityNode)/")
                + this.getSymbolClause(indexParameters, "root($entityNode)/")
                + "insert nodes <kin:Path xmlns:kin=\"http://mpi.nl/tla/kin\">{base-uri($entityNode)}</kin:Path> after $copyNode/*:Identifier\n" // when using a basex version younger than 6.62 the "after" fails re attributes: after $copyNode/*:Identifier" maybe copy is failing to keep the namespace, for earlier version the following can be used "into $copyNode"
                // todo: test if "insert after" take longer than "insert into"
                + ")\n"
{'fraction_non_alphanumeric': 0.1465636654235482, 'fraction_numerical': 0.005327650506126798, 'mean_word_length': 2.48968209704406, 'pattern_counts': {'":': 0, '<': 101, '<?xml version=': 0, '>': 105, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 8}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '139385', 'n_tokens_mistral': 5234, 'n_tokens_neox': 4994, 'n_words': 1061}